• Share
  • ?
  • Profiles ▼
  • Communities ▼
  • Apps ▼

Blogs

  • My Blogs
  • Public Blogs
  • My Updates
  • Administration

This community can have members from outside your organization. Software Development on the Cloud Exploration

  • Log in to participate
c06ef551-0127-483d-a104-cdd02b1cee31 Blog

▼ Tags

 

▼ Archive

  • March 2015
  • January 2015
  • February 2014
  • October 2013
  • August 2013
  • June 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012

▼ Blog Authors

Software Development on the Cloud Exploration

View All Entries
Clicking the button causes a full page refresh. The user could go to the "Entry list" region to view the new content.) Entry list

Swagger/Apiary/RAML versus REST

Martin.Nally 0600016EKX | ‎ | 4 Comments ‎ | 10,868 Views

Swagger/Apiary/RAML versus REST

There is a style of API that has become very popular that is often documented with tools like Swagger, Apiary or RAML. This style of API is often colloquially called REST, although it is not a hypertext style and so does not conform to the formal definition of REST. I'll call it 'pseudo-REST'. This note uses a worked example to show how this style is different from a 'hypertext-REST' API, what the 'hypertext-REST' equivalent of the API would be, and what the advantages of the hypertext-REST style are.

 

Summary

I believe the 'hypertext-REST' API is simpler and easier to use for the client and achieves better decoupling of the client and the server. I think that any server implementer or designer who wishes to offer clients the best possible API should consider using the 'hypertext-REST' style, rather than the 'pseudo-REST' style. API documentation tools should be enhanced to support the 'hypertext-REST' style. The 'hypertext-REST' API style is slightly harder to implement on the server, because the server has to take responsibility for translating between URLs and database keys. In the 'pseudo-REST' style, this responsibility is pushed to the client, so simplicity for the server is traded for simplicity for the client.

 

The example

Assume an application that stores information about dogs and owners. Each dog has a name, breed, date-of-birth, and a reference to its owner. Each owner has a name and address.

 

The implementation

Assume that the implementation exposes URLs like the following:

/dogs
/dogs/{dog-id}
/people
/people/{person-id}

Clients of the API can POST new dogs to /dogs, and new owners to /people. Clients can GET, PUT (or PATCH) and DELETE using the URLs of individual dogs and people. You are all very familiar with this pattern.

Both the pseudo-REST version of my example and the hypertext-REST version of my example can use the same URLs in the implementation, and support the same operations on those URLs. I think this similarity is part of the reason that so many people confuse pseudo-REST with hypertext-REST. However, there is a significant difference in the information that the client has to know when using the two styles.

 

The pseudo-REST API

In the pseudo-REST example, the representation of a dog might look like this in JSON:

{
"name": "Lassie",
"breed": "Collie",
"date-of-birth": "1940-01-01",
"owner": "123456"
}

 

In the pseudo-REST style, the link to the owner is represented by an opaque identifier - 123456. In order to use this ID, the client of the API needs a second piece of information - the URL template for people, i.e.

/people/{person-id}

The client will also need other information, like the domain name of the server, and any base path segments that need to be prepended to the URL template. Swagger and similar tools provide languages for documenting all this information for clients. Using this information, a client can manufacture the following URL:

http://example.org/people/123456

 

The 'hypertext-REST' alternative

In a 'hypertext-REST' API, the server would implement the same URLs, but the representation of a dog is slightly different:

{
"name": "Lassie",
"breed": "Collie",
"date-of-birth": "1940-01-01",
"owner": "http://example.org/people/123456"
}

 

In the 'hypertext-REST' version of the example, the link from the dog to its owner is represented by an opaque HTTP URL. This illustrates the 'hypertext' characteristic of the 'hypertext-REST' model.

In this style of API, URLs are opaque to the client – the client does not manufacture a URL according a URL template, so the client does not need to learn URL templates and the API documentation does not have to describe them. This provides a significant simplification for the client. It also helps decouple the client from the server, allowing the server to change the URL structure in the future (it has to continue to support URLs it has already given out, of course, since they may have been bookmarked).

 

Documenting the two styles

There is good tool support for documenting the pseudo-rest style. Here is an Apiary description of my example:

image

 

 

Using these tools to document a 'hypertext-REST' API doesn't appear to be easy, because they all seem to assume a URL is described in a template based on a path. In the 'hypertext-REST' model the URL structure is server implementation detail subject to change that does not appear in the API description. Here is an approximation using Apiary.

image

 

 

This is almost what I wanted to say, except for the '/' character before each {xxx-url} entry. The '/' would imply that the {xxx-url} value should be post-pended to http://example.org/ to form an URL. This is not the intention - {xxx-url} is already a complete URL. Unfortunately, Apiary appears not to accept an entry that does not have the leading '/'. Note that the example GET that Apiary generated is also not what I wanted. What I wanted was this:

GET <path and query string from {dog-url}> HTTP/1.1
Host: <host from {dog-url}>
Accept: application/json

It is possible that Apiary can do what I want and I just don't know how - let me know if you know something I don't.

 

Other differences

In the 'hypertext-REST' style, a URL provides both the identity and the location of a resource. In the pseudo-REST style, the identity and the location are separate, and the API client manufactures a location URL from the identity. Because of this, in a pseudo-REST style, it makes sense to define URLs that look like this:

http://example.org/V2/dogs/123456/json
http://example.org/V2/dogs/123456/xml
http://example.org/V1/dogs/123456/json

The intention of the first of these URLs is to provide access to a V2 JSON representation of the Dog that is identified by the id value 123456. The other URLs are analogous. This approach is reasonable in the pseudo-REST model, because in that model URLs only represent location – identity is represented by the value 123456.

While the above URLs are reasonable in the pseudo-REST model, they are not reasonable if you are trying to follow the hypertext-REST model. The reason is that the URLs above would each define a new and different resource, which is not the desired outcome[1]. In the 'hypertext-REST' model, you would do this instead:

GET /dogs/123456Host: example.org
Accept: application/json
Dog-Version: V2

In other words, you would put the 'V2' and 'JSON' information in headers, so that the URL itself – which indicates identity – is unaltered.



[1] Even in the hypertext-REST model, it is possible to define these additional URLs, but they cannot be used to link between resources – a 'canonical' URL like http://example.org/dogs/123456 has to be used for linking. The OpenStack API is an example of this model in use. Since in the 'hypertext-REST' model you don't want the client to manipulate URLs, you are also motivated to link all these resources together so the client can find them. In total, this results in a more complex model for the client and the server.

 

Modified on by Martin.Nally 0600016EKX
  • Add a Comment Add a Comment
  • Edit
  • More Actions v
  • Quarantine this Entry
Notify Other People
notification_ex

Send Email Notification

Quarantine this entry

deleteEntry
duplicateEntry

Mark as Duplicate

  • Previous Entry
  • Main
  • Next Entry
Feed for Blog Entries | Feed for Blog Comments | Feed for Comments for this Entry