Mapping 9P to REST

Now that the PHP bindings to libixp are somewhat usable, I’ve moved on to the JavaScript portion of my project. The first (and easier!) part of it is to map 9P to a RESTful scheme, so traditional web developers can use 9P without having to learn anything new.

The PHP bindings to libixp was an important pre-requisite to achieve this: presenting a REST interface to an existing 9P serve would require a “bridge” at the middle, to convert REST requests to 9P requests and vice-versa with responses. This “bridge” may be present at any location that is mutually accessible by the client wanting RESTful access and the server providing the 9P service. This bridge can be easily coded in PHP using the new libixp bindings.

To those not very familiar with REST, it is simply a way of accessing resources using plain-old HTTP. It’s become quite popular with web developers these days, as a much simpler alternative to SOAP. A lot of web services these days are RESTful, including those offered by Amazon and Yahoo.

From the client’s perspective, accessing a 9P resource boils down to 4 things: reading, creating, modifying and deleting. These operations map neatly onto the GET, PUT, POST and DELETE HTTP requests, respectively. And thus, we have our REST URI scheme. This scheme would be enough if my bridge exposes only a single 9P serve as a REST service. As an example, suppose I start a bridge at http://plan9.kix.in/rest/ that exposes only the tcp!sources.cs.bell-labs.com!564 9P serve, to read the file named ‘lsr’ I would perform a GET request at http://plan9.kix.in/rest/lsr.

However, the plot thickens when I want to design a bridge that allows access to any 9P service (which is definitely better). Now we need to encode the information represented in Plan 9 as: tcp!sources.cs.bell-labs.com!564 into a HTTP URI. The intuitive thing to do would be something like: [ROOT]/[PROTOCOL]/[9P-URI]/[PORT]/[FILE-PATH].

Hmm. That leads to really long URI’s like http://plan9.kix.in/rest/tcp/sources.cs.bell-labs.com/564/lsr. Besides that, there are several things that need to be worked out. What happens when you do a GET on a file that is actually a directory? What about parameters to GET that you usually pass to a read() function: Suppose you want to read the first 1024 bytes of a file only?

Comments and Suggestions welcome :)

P.S.: Thanks to some pointers by Kris, the PHP9P client example shown in the previous post now handles binary files correctly.

Posted by Anant on July 26th, 2007 in Plan9, SoC | 1 Comment

Some more on Object Oriented PHP Extensions

Hopefully this is the last of the series on Object Oriented PHP Extensions. We left the last post with a question of how to create objects of a certain class in a method of another. This is especially relevant to the libixp extension, since classes like IxpStat, IxpQid and IxpCFid don’t have any constructors of their own, but are rather returned by methods of the IxpClient class. For example, an open() on IxpClient returns a IxpCFid, and the IxpQid is a property of the IxpStat and IxpCFid classes.

How do we get this to work? The helpful folks at #php.pecl on EFNet pointed me to a few examples in the existing PHP codebase that do this. First, you need to initialize an object – which essentially involves:

  • Calling ALLOC_ZVAL on the zval.
  • Setting the type to OBJECT using Z_TYPE_P.
  • Calling object_init_ex(), which in turn will call the corresponding create_object method for the class entry.
  • Setting the object’s refcount to 1.

Once you’ve done this, most often you’d need to set up certain properties on the class object. In libixp’s case, we need to populate IxpStat’s, IxpCFid’s or IxpQid’s properties. You can create a method to populate each classes properties. I use a set of PROP_SET_* macros to update properties correctly. Check out the code to clear things up – object_instantiate() is the generic method for allocating memory for a object, and the PHP_*_initialize() set of methods set properties for particular classes. These functions are used in almost all of IxpClient’s methods.

Before signing off, another quick word about using properties in your classes. If your class doesn’t use any properties, you can get away without doing any memory allocation at all, see the FliteTTS extension for an example of this. However, if you do plan on using properties, you need a bunch of methods for allocating memory to the HashTable that will hold the properties, as well as the structures that your class will use. You can create a generic method create_object_ex() that does this, and then create two more methods create_object_new() and create_object_clone() that will act as handlers for new object creation as well cloning. These handlers are set during the class initialization (most probably located or called in PHP_MINIT) by setting the create_object member on the class entry struct and the clone_obj member on the classes’ standard object handlers.

Posted by Anant on July 6th, 2007 in Plan9, SoC | No Comments