A little introspection, if you please...

chromatic on 2002-08-24T05:49:18

One of my last acts at my current job is writing a server that speaks SOAP and/or XML-RPC. Another developer is writing the client, in Python. I've used XML-RPC before, but hadn't done more than read through the docs for SOAP::Lite (and reviewed a couple of chapters for the upcoming Programming Web Services with Perl book). It's quite impressive, though.

For performance reasons during development, we switched our internal protocol to XML-RPC. Writing a server to handle that was also very quick and easy with SOAP::Lite. Writing a forking server is not difficult, either. Where the Python client is multi-threaded, I'm using multi processes as Unix intends!

Since several users can use the application at the same time, we're implementing access controls. Different user accounts exist, with different permissions. Some accounts only have read access, others can update, and still others can delete.

I like the way SOAP::Lite automatically dispatches requests to a specified package, but building in access controls to every method is too much work.

I created a proxy object (and not in the Matt Sergeant sense) to which SOAP::Lite autodispatches. The real work is done in the server object. The proxy object actually implements the access controls, creating user sessions, checking magic cookies, and testing if the user has the proper credentials to perform each operation.

The remaining issue was to identify the accessable methods in the server object and to mark them with the permissions they need. Maintaining a separate list somewhere struck me as too much work -- I'd have to keep updating code in two places. That's insufficiently lazy.

What I did was to use Attribute::Handlers to create a 'Publish' attribute. Now any method I want to be publicly available needs that attribute. Publish also takes an argument, the necessary permissions. The attribute handler stores the name of the method, a reference to the method, and the permission string. The proxy object calls get_methods(), receiving this data structure. It installs wrappers around each of these methods in the proxy object itself. That way, they're visible to the SOAP::Lite dispatcher, and I only have to resume a user session and check permissions once.

Through this all, I'm pleased to note that my decompisition skills are improving. The Once and Only Once principle really pays off -- if you get in the habit of factoring out common code, it's amazingly easy to add new features. Nearly everything that is reusable is reused.

Finally, a legitimate reason to use attributes and typeglobs in the same program.


We've had to do that...

james on 2002-08-24T09:41:05

...with Vx, which is our web services-based digital media platform.

Another problem we had is making a note of all the objects that leave the system under one user, and keeping track of that against all the objects that come back to the system from that user (ie, if the user has an object we didn't give him, then we have a problem). And of course you want to make sure that the person at the other end doesn't monkey with the data in the objects...

Maybe it would be worthwhile ripping that out of Vx and releasing it as a seperate module...

Hmmm...

Thanks for the idea!

lachoy on 2002-08-24T15:39:23

I just wanted to say thanks for this post. It immediately sparked an idea to implement sometime later when I finally need to use SOAP. (Won't be long now :-)