Designing a RESTful web API
scotch.io
scotch.io
1. Explicit versioning, stuffed into each resource's URI
This is really bad, it shows the designer has only experience with RPC, but not resource-oriented. Bumping the server version breaks all clients for no good reason. Imagine if the Web sites worked that way: you have to upgrade your browser before you can visit an updated site. The correct way to do it is to version gradually, and express a changed semantic for a resource type by coining a new link relation for it. Do not put semantics in a resource URI as the article advises!
2. Utter lack of hypermedia controls
The article mentions CSV as possible media type for that entity. As we all know, CSV does not have or support hyperlinks, forms or any other hypermedia control. This is a serious oversight because it's not possible to have a RESTful architecture without those controls. Remedy: the designer must implement controls in the message body where natively supported by an entity type (e.g. XLink or XForms for XML) or else fall back to the message header (e.g. Link header/URI templates for CSV).
3. Fixed URI structuring
This is related to point 2 above. Example: </v1/stores/near?lat=12.34&lon=-12.34> How does the client know how to construct this URI? The article mentions no hyperlinks or other controls. It does say "define the right endpoint names" which I surmise go into some sort of specification document, which is wrong. Doing so makes the server lose control over its URI space and creates unnecessary tight coupling, which is brittle. Express typed resources with link relations, not with the resource URI structure! There must be only exactly one entry point (bookmark) for the client to know, all other URIs are derived by traversing the resources through controls!
4. Lack of clue about security
The article talks about authentication with OAuth or HTTP basic authentication. OAuth is chiefly for 3rd party authorization, no wonder the article's author is confused. Implementing this is workable, but overkill if all you need is authentication, making it much more difficult for a programmer to implement client software correctly, but brings no benefit. HTTP basic authentication is either clear text or susceptible to replay attacks. <http://www.xml.com/pub/a/2003/12/17/dive.html> Remedy: it's 2014, just use TLS. Let the transport layer take care of authenticating a user, the application code on the server is free of authentication.
5. Reinvents the wheel for error handling
Established draft standards exist. Use them. <http://www.mnot.net/blog/2013/05/15/http_problem> <https://github.com/blongden/vnd.error>
tl;dr Article is pretty much amateur hour, I advise the interested reader to get one of the classic books on REST instead to learn it properly. <http://oreilly.com/catalog/9780596529260> <http://oreilly.com/catalog/9780596805838> <http://oreilly.com/catalog/9781449358068>
Update: angle brackets are reserved characters for delimiting a URI, not part of a URI. Hackernews, you are out of compliance with RFC 3986, please fix your shit.
e.g. For Salesforce's REST API you can see all the versions at:
http://na1.salesforce.com/services/data/
Documentation:
That's a great point! But, wouldn't you need to update your code anyways when migrating to a newer API version? The idea is that you only release a new API version for backwards-incompatible changes. E.g. when we launched fields for Geocodio[1], all you needed to do was append a "&fields=x" parameter to your query string, so that didn't require a new API version.
So I'm not sure what the exact purpose of getting the version number as a resource would be?
If I install a client application where there are multiple implementations of the same service (not the case with SFDC) I just want to have to know the URL for their service not to have to work out which version of the service this particular application works with and which are available - the application should be able to do that.
If the size of your resource is e.g. 100KB, and you have 10 different versions, then your responses are 1MB each -- 9 times larger than they have to be. This can result in significant bandwidth costs, depending on your number of users and their behaviour.
All I was saying is that if you do run multiple versions of the same interface on different URLs then it's quite nice to have these versions themselves treated as resources you can find out about through the interface. That's what Salesforce do and, in my experience, I think it is simple and elegant.
There's not really a reason to give away anything else, it's usually because something is broken (database connection and whatnot) and the developers are probably already aware of it with tools such as Bugsnag[1] and alike.
In general for error messages, exceptions should be handled gracefully and output a simple message that is understandable for the user. It might also be ideal to include an error code with the JSON response if you have a lot of different error messages that happens under the same HTTP status code (e.g. 400 Client Error).
- Including the clear text API key in the URI makes it very easy for anyone listening in to gain unauthorized access. To get around this, one can either enforce HTTPS, or require a hash of a pass phrase.
- Another option to look into is Kerberos.
I prefer single token methods like jwt.