It seems that every time I talk to another developer about building an API, there tends to be some confusion on terminology and implementation details. While many will say that they are implementing a RESTful Web service, when they start detailing the implementation it becomes clear they really mean RPC. I’m not sure where the confusion stems from, as both standards are pretty well documented. Still, I’m amazed at how few REST implementations get it right.
Both REST and RPC have their place, and may even coexist within a single project. They simply provide different ways of accessing things, and each has its own strengths and weaknesses which make it more or less suitable for a given purpose.
What is RPC?
RPC means Remote Procedure Call, and is used to call a function or method exposed on a remote server. When discussing RPC, most developers tend to be referring to either XML-RPC or SOAP. Both are simply protocols, and can be used as completely valid RPC implementations. I’ve also seen many developers happily role their own implementations as well.
Most RPC implementations use XML or JSON to pass messages or payloads between the client and the server. The request message would contain the name of the remote method to call, along with the method arguments. The server would then respond with a message containing the return value of method and any other messages.
If an API uses SOAP, XML-RPC, or uses URLs like http://example.com/api/method?arg1=foo, it is (most likely) an RPC interface. There are many ways to implement an RPC API, but in the last case of a home-grown API, requests might look like those below.
To request a list of user accounts in XML format from an RPC API, the request URI might be similar to this:
http://example.com/api/getUserList?format=xml
The API should send back an XML payload of user accounts, or it may respond with some sort of error message instead. In either case, a 200 OK status code will probably be returned.
The same API may allow the creation of a user account, either using GET or POST (broken apart for readability):
http://example.com/api/createUser \ ?format=xml \ &firstName=Example \ &lastName=User \ &displayName=Example+User \ &passwordHash=5f4dcc3b5aa765d61d8327deb882cf99h238
In this case, the API would probably respond in much the same way, with an XML payload containing either a success flag or an error string.
What is REST?
The term REST means Representational State Transfer, and is a pretty popular buzzword on the Internet. A RESTful API presents application objects as Web resources, and uses standard HTTP methods and headers to pass information back and forth.
Communication with a REST endpoint is mostly done using the GET, POST, PUT, and DELETE HTTP methods. These roughly translate to read, create, edit, and delete actions, respectively. Parameters are passed using HTTP request headers or query strings, and responses can be returned in a number of formats (XML and JSON being very common). Various HTTP error codes are used to indicate the state of the resource following the request.
The request body of a RESTful call to return a list of of user accounts in XML format may look like this:
GET /api/users HTTP/1.0 Accept: text/xml
The response may be a 200 OK status with an XML payload, or it might be a 401 Unauthorized if the API requires authentication but the credentials were not included with the request.
Creating a new user resource is also very easy, as shown below:
POST /api/users HTTP/1.0 Accept: text/xml Content-Type: text/xml Content-Length: 227 <?xml version="1.0" encoding="UTF-8"?> <user> <firstName value="Example" /> <lastName value="User" /> <displayName value="Example User" /> <passwordHash value="5f4dcc3b5aa765d61d8327deb882cf99h238" /> </user>
If the new user resource was created successfully, the server may respond with a 201 Created status, and a Location header pointing to the newly created resource.
201 Created Location: http://example.org/api/users/31337
A request to the URI provided in the Location header should return a payload containing the new user record.
Conclusion
Hopefully at this point the basic differences between the two API types are a little clearer. In my opinion, one interface type is not inherently superior to the other, and both can be used very effectively given proper implementations (and documentation!).
While I centered my examples here around a fictional user API which translates well into both interface types, I think it's important to also point out that there are some functions an API might have to support that don't work nearly as well. One such example might be an API which is used to perform some sort of action, such as processing a payment. This type of action would work very well in an RPC interface:
http://example.com/api/processPayment \ ?format=xml \ &amount=313.37 \ &cardNo=4111111111111111
If you know how to do this in a RESTful way, please share! ;-)