A wee journey into RPC

oliver on 2006-11-25T11:20:16

Let's talk a little more about RPC, and YAML::RPC. A lot has changed in my mind in the past few days (slow bus journeys this week, meaning I have time to really mull things over).

YAML::RPC is cool, as I said before, but there are a couple of things about it that annoy me. One of them is that each handler must be registered in the server's config. This means you have one file with your actual handler sub definitions, and another with their names (or mapped names), and this tends to cause me to make mistakes.

The other problem with YAML::RPC is that it's, well, YAML, and whilst I love YAML for its simplicity, readability and syntactic brevity, it's also prone to nasty bugs. For example, YAML represents the undefined value with a tilda (~), but in some circles this symbol can mean a user's home directory. If you don't take good care of your quoting, then in serializing and deserializing data you can turn a filesystem path into an undefined value. There are a few more examples involving the well-known whitespace issues, meaning that oftentimes you'll end up having to base64 encode data before serializing into YAML. This effort kind of undoes all the goodness brought about by YAML's syntax, don't you think?

So what I really want is an RPC system that avoids these two annoyances, and is a little more flexible than YAML::RPC in its dispatching mechanism, which is just a dumb call the sub thing. Okay, so I'll rewrite YAML::RPC to be Data::Serializer::RPC, and then we can use any data format, and get encryption/compression too if we want. I still need a flexible dispatcher and handler registration mechanism, and I want to have more options than just ucspi-tcp or other STDIN/STDOUT wrappers for network connectivity.

Seeing as the client-side of this will be a Catalyst model, it did strike me that Catalyst already has a lot of what I want... the flexible dispatcher, plugins (oh, yes, I was going to make it all pluggable using NEXT or Class:C3 because I like things like that), and network connectivity for free.

Hmm, why not just subvert Catalyst into an RPC system instead?

Around this time I happened to pop back onto #catalyst to ask about their plugin system, and got chatting with the nice folks there, and explained my plans. Matt Trout, who is a fountain of ideas, piped up with "You should look at XMLRPC, or REST." No way was I going to touch XMLRPC; I get a rash every time I use XML. But this REST thing rang a bell, and so I went googling and reminded myself what it was all about.

Okay, so REST is basically just what the web is already doing, but as well as GET and POST for web pages, you use DELETE, PUT, etc (as with WebDAV) and call the things you get "resources". The body of the HTTP response, as we know from things like SOAP w/HTTP can be any old data. It could even be YAML! So rather than use YAML::RPC, which has its own calling syntax, use HTTP and GET a resource, or PUT one. The Wikipedia REST page does a reasonable job of explaining how REST methods can map to CRUD methods.

The final nail in the coffin for my YAML::RPC project was that some bright spark has already written the necessary frobnits to make Catalyst into a REST server, and they even use Data::Serializer in the transport. That's enough for the backend, so all I need to do is write a REST Model that acts as a client; this is simple and just uses standard Perl LWP. Hopefully that should sneak its way out to the CPAN before too long; I've just had a reply from my director giving open source release on the code, which I'm pleased about.