REST is a popular architectural style that has been the go-to design for web-based APIs for years. The style has defining constraints, but it is not a protocol and there is no official standard. REST is like the pirate’s code in the Pirates of the Caribbean movie franchise, in that REST “is more what you would call guidelines than actual rules.” As such, not everyone follows the guidelines exactly or interprets them the same way.
This can lead to some confusion and debate as to what is and is not considered RESTful. At the same time, one can look at this flexibility as an opportunity to pick and choose what will work best for their needs. In this article, we briefly discuss some web API design options and explore some of their strengths and shortcomings.
What REST is – and isn’t
For some, REST simply means using a service that is not SOAP. SOAP is another widely used protocol, but some stay away from it due to its complexity and the extra overhead that it requires. You would be hard pressed to find a REST-related article where SOAP is not mentioned. You will likely find comments about how great REST is because REST uses JSON and SOAP uses XML.
People often mistakenly think that REST is defined by the JSON language format, and when they say they want a RESTful service what they really mean is they want a service that supports JSON. REST is not as simple as that, and it is not confined to any one language format: it is an architectural style and not a specific protocol. Conversely, JSON is not exclusive to REST, as JSON is also available in Remote Procedural Call (RPC) APIs.
So, with that out of the way, the rest of this article will assume that the reader is familiar with the general style of REST. If you wish to learn about REST in more detail then feel free to read the dissertation it was based on – or if you’re not into heavy reading, check out the REST wiki.
Comparing three web API options
Now, let’s look at three different approaches you can use for web APIs:
- REST – Representational State Transfer (REST) web APIs are “resource” oriented. RESTful APIs synergize well with CRUD applications and other forms of data resource management and manipulation.
- RPC – Remote Procedural Call (RPC) web APIs are “action” oriented. They enable the user to call a remote method to complete an action as though it were local. This is similar to importing and using the methods from a local library API.
- Hybrid – Hybrid designed web APIs incorporate both the RESTful style and RPC-based design methods. Some RESTful APIs will include RPC design to add action methods where strictly RESTful resource-oriented methods are not appropriate.
Since REST is resource oriented it is also useful for resource discovery. For example, if a Service Objects client was interested in all the cities or ZIP codes for a state then a RESTful API for discovering those resources and drilling into them for details would be ideal. This approach will also work well for suggestion and IntelliSense applications where several queries to find an address would be acceptable.
By comparison, users looking for address validation could find that having to make several queries would be cumbersome – especially if their data is incomplete or partially invalid. Most of our users do not always have complete data, and lean on us heavily to parse through and correct any garbage or mistakes to fill in the gaps and return an intuitive and standardized response.
RESTful example: Address Validation
Let’s briefly explore what creating a RESTful address validation service would look like. We’ll start by coming up with a way for the user to submit an address for validation.
For this exercise, the theoretical service will be hosted on the following domain and path.
Domain: example.serviceobjects.com
Path format: /AddressValidation/{State}/{City}/{ZIP}/{AddressLine1}/{AddressLine2}
The above format lends itself more to address discovery and would be better suited with a /FindAddress path name; however, this application’s primary job is validation and not discovery so let’s continue.
Let’s test the service using the Service Objects office address as an example.
Path example: /AddressValidation/CA/Santa Barbara/93101/27 E. Cota St #500/
Unfortunately, the above example will fail to validate correctly due to the pound/hashtag (#) character. We know that the # symbol is a special URL character and that it is used as a fragment identifier. Commonly referred to as anchor in HTML. Its inclusion means that the URL path is prematurely terminated at the # symbol.
In this case, the API can respond in a few ways. It can return an HTTP Status code of 400 (Bad Request), but that isn’t too helpful to the user. It can also accept the request, but since the service is unable to see anything past the # symbol, the full address will not be validated. This is problematic, not only because the full address is not being validated, but what would be an acceptable response from the service? Validating the address as-is would be misleading to the user, and the service itself is unaware that parts of the address are missing. In the end, for this example, it would be best for the service to return the 400 status code for safety.
Now let’s try a different path format:
Path format: /AddressValidation/{State}/{City}/{ZIP}/{AddressLine1}/{UnitNumber}/{AddressLine2}
Path example: /AddressValidation/CA/Santa Barbara/93101/27 E. Cota St/500/
The above path format and example work, but it requires the user to parse out the apartment number from the address beforehand, and it is still susceptible to malformed requests due to special URL characters.
As we have just demonstrated, the path parameter approach has some shortcomings. More details and examples are available in a past tutorial. Fortunately, REST is not limited to one way of making requests; however, depending on one’s interpretation this is where this service and many others start to deviate from RESTful guidelines.
Foregoing the path parameter approach entirely, we could use query string parameters or POST requests.
Query string example: /AddressValidation?AddressLine1=27 E. Cota St #500&AddressLine2=&City=Santa Barbara&State=CA&PostalCode=93101
In the above example, the query string parameters can be URL encoded, and there is no fear that the full address will not be passed in. There is also the option to use POST, but using POST instead of GET to read a resource is generally not done as it goes against REST guidelines. However, it is not uncommon to see many services use POST in ways outside of the REST guidelines.
For presentation sake, let’s continue with our example using POST and JSON.
JSON POST request:
POST /AddressValidation HTTP/1.1 Host: example.serviceobjects.com Content-Type: application/json { "AddressLine1":"27 E. Cota St #500", "AddressLine2":"", "City":"Santa Barbara", "State":"CA", "ZIP":"93101" }
A strictly RESTful response would be as simple as an HTTP 200 status code with a response like this:
{ "Status":"OK" }
If we provided an invalid address, for example by changing the suite number from 500 to 5,000 which does not exist, the RESTful response would then potentially return an HTTP status code of 404 with an output of:
{ "Status":"Not Found" }
The above output examples are too simplistic and not informative enough. The service could return a status description of “Address Not Found”, but the user is still left with very little information to work with. Our users rely on our services to not just validate their data but to also help inform them on how to proceed with using their data.
Following the RESTful style guidelines, the output could also contain an Address ID that can be used to reference the address and list details for it.
{ "Status":"OK" "AddressID":"931017602254" }
POST /Address/931017602254/Details HTTP/1.1 Host: example.serviceobjects.com Content-Type: application/json { "Satus":"OK" "Address1":"27 E Cota St Ste 500", "Address2":"", "City":"Santa Barbara", "State":"CA", "ZIP":"93101-7602", "DPVCode":"1", "BarcodeDigits":"931017602254", "CarrierRoute":"C006", "IsResidential":"No", "FragmentHouse":"27", "FragmentPreDir":"E", "FragmentStreet":"Cota", "FragmentSuffix":"St", "FragmentPostDir":"", "FragmentUnit":"Ste", "Fragment":"500", "CongressCode":"24", "CountyCode":"083", "CountyName":"Santa Barbara" }
This RESTful style is not quite user friendly in that it requires the user to perform two queries: one to verify the address, and another to retrieve details for it. A big part of the problem stems from REST being “resource” oriented whereas Validation and Verification services are “action” oriented; therefore, lending themselves more towards the RPC-based design.
That’s not to say that the RESTful service cannot be made more user friendly. A hybrid approach can be taken, and the service could be expanded to be more informative by adding parameters to retrieve additional data so that only one request query is needed.
POST /AddressValidation HTTP/1.1 Host: example.serviceobjects.com Content-Type: application/json { "AddressLine1":"27 E. Cota St #500", "AddressLine2":"", "City":"Santa Barbara", "State":"CA", "ZIP":"93101", "IncludeDPVCode":"Yes", "IncludeBarcodeDigits":"Yes", "IncludeCarrierRoute":"No", "IncludeResidentialIdentifier":"Yes", "IncludeAddressFragments":"Yes", "IncludeCongressCode":"No", "IncludeCountyCode":"No", "IncludeCountyCode":"Yes" }
Output:
{ "Satus":"OK" "Address1":"27 E Cota St Ste 500", "Address2":"", "City":"Santa Barbara", "State":"CA", "ZIP":"93101-7602", "DPVCode":"1", "BarcodeDigits":"931017602254", "IsResidential":"No", "FragmentHouse":"27", "FragmentPreDir":"E", "FragmentStreet":"Cota", "FragmentSuffix":"St", "FragmentPostDir":"", "FragmentUnit":"Ste", "Fragment":"500", "CountyName":"Santa Barbara" }
However, using an RPC-based design and forcing it to try and conform to the RESTful style doesn’t necessarily lead to a better user experience.
Why flexibility is important
REST, RPC and hybrid designs each have their own merits and uses. It’s important to choose a design that works best for the given situation. That’s why Service Objects chooses a hybrid approach for our services that leans more toward the RPC-based design, since it suits the action-oriented usage. With validation services there are often many gray areas and edge cases to deal with that work best with custom action-based verb commands.
In a RESTful style, custom verb commands are to be avoided, and some would argue that any use of them would, strictly speaking, not be REST. However, many services do make use of both in a hybrid approach and even Google’s API Design Guide states that , “both RPC APIs and HTTP REST APIs are needed for various reasons, and ideally, an API platform should provide best support for all types of APIs.” So, whether you want to use HTTP GET, POST or SOAP with XML or JSON, the Service Objects DOTS Web Services have you covered.