Some REST best practices
bourgeois.me
bourgeois.me
I'd disagree. If I were critiquing a non-REST API over HTTP, I wouldn't get upset about requiring a call to POST /processOrder at all, whereas I'd begin to convulse if they said it was a REST API.
Hackers should pay attention to:
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
I have also found collection+json and hypermedia application language (HAL) to be useful.
Plus, I have spent a bunch of time reading the Restful Web APIs book from O'Reilly. Useful for me, as a relative newbie, in providing some logical foundation to start from . . .
I've found a number of people who point at the Github api as a good example of a RESTful api that includes hypermedia links for clients to follow rather than constructing URI requests manually. It looks good to me.
Money quote:
REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them. That’s fine with me as long as you don’t call the result a REST API.
Can you cite your latter point, since that's contrary to how I've seen HATEOAS explained? Many libraries do expose a browser-navigable form of the API, but I can't see how that's how it's originally defined nor it being a requirement.
I stated that HATEOAS is widely misunderstood so it isn't surprising that there are conflicting descriptions out there. No matter what your interpretation, this principle is about hypermedia and application state and says nothing about what a URL should or should not be.
No, it is strictly a REST principle that the meaning of URLs other than the entry point is defined completely by the context in which they are used in resource representations and the definition of those resource representation (i.e., media types).
An implementation of a REST API may happen to present URLs with a consistent relationship of location structure to semantic meaning in the API, but that's entirely outside the scope of the REST API per se.
> If we are talking about good practices, would your rather work with an REST API with readable, concise URLs or not?
If you are using HATEOAS, URL format, readable or not, isn't a feature of the API at all (its a feature of a particular implementation of the API, but its one that clients don't need to be aware of.)
> Maybe I am missing the point but the URL is one of the major building blocks of REST and choosing quality ones is a large part of API design.
You are missing the point. URLs as opaque identifiers is one of the major building blocks of rest, and if you are worried about choosing one as part of "API design", you aren't building a REST API.
The resource representation (media type) should tell you what the URLs used in it are for, not the URLs themselves.
> I stated that HATEOAS is widely misunderstood so it isn't surprising that there are conflicting descriptions out there. No matter what your interpretation, this principle is about hypermedia and application state and says nothing about what a URL should or should not be.
If you need to communicate the URL structure and identify relative URLs for various endpoints to describe an API, it is not a REST API following HATEOAS; "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API)." [1]
HATEOAS clearly is misunderstood, as you've just demonstrated.
[1] http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
"The only thing you can use an identifier for is to refer to an object. When you are not dereferencing, you should not look at the contents of the URI string to gain other information."
No, it doesn't. In fact, a REST API can fully meet the requirements Fielding lays out without having any implementation that uses any communication protocol used by any web browser. REST is an architectural pattern that is independent of communication protocols.
Hypermedia as the engine of application state
Hypermedia means HTML, period. Putting a list of URLs in a text or JSON response does not magically make it hypermedia.
Engine of application state means that all representations of the resources must be possible.
Combine those two and it means that all functionality must be accessible to and from the text/html content type. It must be able to handle all supported HTTP verbs and no fancy request headers that are not supported by HTML forms or hyperlinks.
Um, no. XHTML and SVG are hypermedia.
JSON isn't hypermedia, but you can define hypermedia formats that use JSON (just as SVG uses XML).
Wrong. Any resource representation that can contain links to other resources with semantic identification of the relationship they have with the current resource is hypermedia. HTML is particularly popular, but far from the only hypermedia format.
> Putting a list of URLs in a text or JSON response does not magically make it hypermedia.
No, not magically, but if you have URLs with identification of their relationship to the current document in JSON, it is hypermedia. Hypermedia is older than HTML, and extends well beyond it.
> Engine of application state means that all representations of the resources must be possible.
No, it doesn't. HATEOAS does not mean that all resources must have hypermedia representations, it means that all available actions on the application state (whether read actions or write actions) must be identified to the client through hypermedia. (E.g., through links communicated in hypermedia resource representations wherein the semantics of the representation and the media-type of the resource in which it appears and which applies to the linked resource define the available actions.) A resource representation to which access is provided via a hypermedia link but which does not define additional linked resources need not be in a hypermedia format (that is, some resources may be purely defined by things like straight -- not hyper- -- text resources, or images, or whatever.)
> Combine those two and it means that all functionality must be accessible to and from the text/html content type.
It doesn't mean that at all. What HATEOAS means is laid out most clearly by Roy Fielding in a blog post responding to the way in which his definition of REST had been misunderstood on this point: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
REST isn't about HTML or the Web, though the Web and HTML are the inspiration for the definition of the REST architectural style. REST (and HATEOAS more specifically) requires neither HTML, nor any of the other specific technologies (HTTP, etc.) that define "the Web".
Before and during the time it was written there were existing HTTP based web services that were successful and they didn't follow all the principles outlined in the dissertation. Fast-forward 15 years and the vast majority of successful HTTP based web services still don't follow all the principles. Some turned out to be more useful than others.
HTTP based web services existed before Roy's dissertation and while the formalizing of them helped them mature rapidly, the idealistic principles aren't the final word on the subject anymore. Real world practice now is.
http://en.wikipedia.org/wiki/HATEOAS
key concept:
> "The principle is that a client interacts with a network application entirely through hypermedia provided dynamically by application servers. A REST client needs no prior knowledge about how to interact with any particular application or server beyond a generic understanding of hypermedia. By contrast, in a service-oriented architecture (SOA), clients and servers interact through a fixed interface shared through documentation or an interface description language (IDL)."
a truly RESTful service that follows the HATEOAS pattern doesn't require documentation to be hosted separately. it will supply all the information necessary directly through the RESTful service.
The key concept I understood but I don't get how clients and servers have to be, to just "get" each other in the way HATEOAS implies.
No, it wasn't. Fielding's dissertation, in which REST was defined, argues that a certain set of principles were an underlying foundation of the structure of the WWW architecture in its original construction, proposes REST as a formalization of and update to those principles, and proposes further that updates to the WWW architecture should be reviewed for compliance to the REST architecture. [1]
So REST is a further elaboration of a set of principles inferred from the original HTTP spec, not something present as such in the original HTTP spec.
[1] http://www.ics.uci.edu/~fielding/pubs/dissertation/web_arch_...
In fact, I'm still totally lost as to the usefulness of REST at all, except as a generic term to mean RPC over HTTP except not as clunky as SOAP. Which isn't what REST is. I've yet to see or use an API that was easier to deal with because it was REST.
I've yet to see or use an API that was easier to deal with because it was REST.
Of course not, because people actually want to use RPC, and so shoehorn REST into RPC-like models, which destroy its usefulness.
If you're sitting at your computer and deciding that you're now going to write a client against Service A's API, the point of REST was missed, and Service A might as well have used RPC.
The point of REST is to decouple the client from the specific service, using the Uniform Interface and standard formats to allow clients to interact with any service that "speaks" the same formats.
But nobody's is thinking on those terms. Everyone is still thinking that it's perfectly normal and OK to waste years of developer time rewriting the wheel, over and over again, for each new service that pops up. This is fueled by the services themselves, of course, whose companies want to use their API to lock you in.
So no, while this is the normal mentality, you won't see any major gains from REST.
It works for unattended web clients (like Google's spider) too -- and not just for generating basic listings, but for structured schema-based data to update Knowledge Graph. That's one of the foundations of many of the new features of Google Search in the last several years.
Auto discovery does not mean that links are understood (@rel may help but..) you may need a human to decide but..
Suppose a (rest) application that lists links to its "services" in home page with the "service" page describing the service following a certain standard. You may have a bot that checks periodically the application for services you are interested in and be notified if a new service is available, with the possibility to navigate to the page and possibly subscribe.
1. why do you necessarily assume that REST API's are only accessed by robots? A human developer can benefit from HATEOAS quite a lot by being able to use the RESTful service's outputs as its own documentation. The developer can discover the features of the API by following links provided in the API outputs.
2. An API client can check that it matches the interface specified by the API just by comparing the URI's it is accessing with the URI's provided by the HATEOAS part of the RESTful service. You can automatically detect changes, breakages, or new feature introduction. This doesn't spare the client developer from having to update their client code, but it gives that developer a powerful tool for getting updates about the RESTful service.
It might need documentation of the special media types it relies on to be hosted separately (one place where most "REST" APIs fail to follow HATEOAS is that they reuse generic media types but rely on out-of-band descriptions of the "real" format of the data, so that a client familiar with only the media type and the data would not semantics of the resource representations being returned by the API.)
http://martinfowler.com/articles/richardsonMaturityModel.htm...
I was expecting more from this HATEOS stuff. Everything I read before sounded like full auto-discovery of APIs.
But the only thing seems to be including possible next URLs in the responses.
Don't get me wrong, this is a good thing. It gives the backend devs more freedom and the frontend devs need less documentation to find out what's possible. But everyone still has to write the interfacing code to these APIs :D
In a HATEOS API, clients need to know exactly one entry point endpoint. Nothing else is hardcoded. There is no Python code that happens to know "if you want to add a widget to a product, you POST to /product/$X/widgets". The API itself tells you where to go.
An acid test: assume your API entrypoint is /api. If your API keeps HATEOS kosher, you could in a serverside update change every other URL endpoint in the application without breaking clients, because the clients would be getting those URLs from the entrypoint URL dynamically anyways.
(That's not really the point of HATEOS, but it's a side effect).
There is nothing wrong with simple HTTP APIs, and a lot wrong with explicitly RPC (verb) oriented APIs in general, so adhering to REST principles isn't an absolute good.
This might be the point where 'dragonwriter tells me I, too, have misunderstood HATEOS. :)
Another small gripe is the notion that a REST client need not have URIs to specific resources/actions hardcoded in them. The fact that you don't hardcode the specific URIs but rather a bunch of link strings that you then use to look up URIs makes this a lot less interesting. The way it's described generally makes it sound as if there is some kind of magical mechanism by which a client actually learns of the existence of a given endpoint, which would truly be magical. Really, all that's happening is that a client knows a name for a specific endpoint that it's looking for, and the API provides a way to look up the specific URI for that endpoint. Makes things tidy, but it doesn't seem like a feature that has much practical impact if you follow a "URIs shouldn't change" philosophy anyway.
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
that said, it was still a good article. I agree with the author on his best practices for JSON API design.
Indeed, and this is why I think "RESTful" APIs are a huge problem - they're largely undefined. We have SOAP for defining these things formally without the need to worry about implementation differences. Unfortunately it was essentially abandoned because it was too complicated and excessive. It would be really interesting to see something SOAP-like with some more modern features and made a bit simpler.
Many times.
I suspect that where you seem to have read "more {modern features}" but ultramancool meant "{more modern} features".
That is, I think the intent was that the features of the otherwise SOAP-like thing would be more modern than the features of SOAP, not that SOAP-like thing would have more features than SOAP and that those additional features would be modern.
Saying something is "RESTful" is a surefire way to find out the ways in which it fails to match up with what some obscure document says.
1. Documentation - If I have to spend the next month doing trial+error to get your API working, thats no good. The best APIs have a page that describes how get up and running quickly.
2. Good error messages - When something goes wrong I want to know what went wrong. The error message being in a consistent format isn't that important, as long as there is a description of what happened. "Oops, an error occurred, try again later" is not a good error message.
Most of the stuff in this article is superficial stuff that I don't think matters.
What the article seems to describe are practices that generate consistent, predictable RESTful APIs, which is exactly how you yield easy to use APIs. This saves both the creator and consumer's time, as debate and decisions over deviations are avoided.
I'm not quite sure why so many comments have gone so negative -- this is hardly a revolutionary piece, yet many of us are creating or dealing with APIs that could do well to take some advice.
Let me into your minds. Show me how you think I think. If you don't know how the people consuming your API think, your API is going to be pretty bogus. If your way of thinking is inimical to me, fine and dandy. Just give me a reasonable way to find out which isn't reading hundreds of pages of Javadoc or similar.
And if the example contains copy-and-pastable code, or reusable functions, so much the better. Make the licenses align, even if the code which implements the API is fully proprietary, and things will work out just fine.
Oh, and if you can't keep your example code working, that says something I need to know, too. Something nasty.
What we're left with are the two problems you described. We have no idea how to actually _do_ anything with the API. And when things don't appear to work, we're left guessing.
Some of the best API "guides" are the ones that break things down by use case and describe how to achieve it. For example, I'm a fan of GitHub documentation: https://developer.github.com/v3/issues/#create-an-issue.
Well, yeah, it's what everyone says, but not so easy to do in practice. Especially in complex apps there's a lot of stuff that isn't actually creating, updating or deleting an object, it is semantically an action. Say, action "send email" (and not some random email, but related or even defined by some business object you are referring to). Or in bookkeeping apps you often need something like "recalculate", which you probably wouldn't like to think of as "updating" because it isn't "take these values and apply to that object", but rather "hey, it's time to make some decision: please run some process (probably, with side effects) and tell us what the result is". Or it might be an action like "moveToQueue<Name>". Or better yet, you explicitly are telling your system to make some interaction with third-party service which is essentially imperative (like GDS, or some external trading API or whatever that isn't an object for your system, but really more like a service for which your app is just a friendly gateway). It is a little bit hard to think of good example right away, because if there is action "purchaseTicket" and there's no object "ticket" in your system you might ask WHY there's no object ticket in your system, but in all specific enough systems there always are situations like this, and mostly for some good reason. And yeah, there's also decisions made for performance sake or simplicity of client-app (like some frontend-side "action queue" so that you can use reactive programming on front-end in more natural way).
So what do I do then? All URLs like "/user/123/order[s]"(PUT,GET,...), "/product/321/comment[s]"(PUT,GET,...) and, suddenly "/sale/copyToAnotherService"? Now that kind of inconsistency is something I really don't like.
…And while I was writing the last one I though about: how should look url for something like "getRecommendedProducts" which depends on both user and product?
Now writing nouns/action names is a bit messy and so not-RESTful, but you always are able to write exactly what you mean by that request.
To really do it, you'd want /emails instead of /email, and then you'd expect that you could access any given email by /emails/<id>, getting a 401 or 403 if you tried to access one that doesn't exist. Further, you could expect that you could then augment the email resource with a status flag, and then you could even sort for sent emails by /emails?status=sent_and_acknowleged or similar.
For your second case, a POST would be a little weird, unless it returned you a new stats_report. I'd suggest changing that to /stats_reports, and have it create a new stats_report object. To view latest, you'd GET /stats_reports/head or something.
GET /product/recommended?user_id={user_id}
the "type" of products you want is a sub-set of all products (recommended). For differentiators I think using params is good. You can then do something like:
GET /product/recommended?user_id={user_id}&rating=5
etc...
Seems clean to me, but also is just my opinion.
If your API could benefit from a particular verb (SEARCH, MOVE, CHECKOUT), just use it. You don't need (more) permission from (another) RFC - RFC 2616 and 7231 [1] already gave you permission to add verbs.
Most libraries and tools support arbitrary verbs including `XMLHttpRequest` and `curl`. Yes, there are a few libraries and frameworks that don't easily support arbitrary verbs, but the ones that have added support for PATCH generally have opened up.
Look, there are two Internets. One for people and one for machines. Our RESTful APIs are intended for consumption by machines, not people. You don't have to wedge everything into GET and POST and abuse query parameters to convey what you really mean.
A framework that doesn't support extensible verbs in 2014 is bound to have more problems than just a failure to implement one RFC correctly.
Precisely, in a way.
- Routes that intended for use by people via clickable links (web browsers and email clients) obviously must use GET; I believe HTML forms are likewise limited to GET and POST by the `method` attribute (I've never submitted a PATCH form myself).
- You may have to interop with intermediate proxies that perform some form of DPI. For example, some proxies know that certain requests can be cached based on a URI. These proxies may not have support for custom verbs.
- Corporate firewalls may whitelist verbs [1].
In general, the idea is to strive to use verbs that have broad applicability in your API, but that doesn't mean every resource must implement every verb (e.g. read-only collections usually don't implement DELETE). But that's just an standard application of the uniform access principle.
[1] http://www.hanselman.com/blog/HTTPPUTOrDELETENotAllowedUseXH...
Keep things sane and stick to GET/POST/PUT/DELETE.
You can't win. Do what is right, and then scale back to what the circumstances allow.
If anyone has anything on implementing more complex REST APIs, I'd be interested in reading it.
EDIT: If we consider adding methods to HTTP, it is easy to imagine a new method, named say CALL or RUN, which would allow arbitrary procedures to be run bound to the requested resource, allowing for a sort of "object-oriented" RPC over REST...
I agree that keeping resource names consistent is good, but using plurals is not the only, and probably not the superior, solution.
Versioning is an idea that gets talked about a lot but can easily create more problems than it solves. Small improvements in APIs should be backward compatible and major ones should be new APIs. Whatever you do, putting "v1" in the middle of your URL is the wrong way to do it. (And so is putting "api" in your URL. It's better to keep your URLs clean of ambiguous and redundant information.)
Nesting resources is an anti-pattern that quickly creates a mess. I've learned this the hard way so please don't repeat my mistakes.
The 3rd principle of REST interface constraints is "descriptive" error messages. It is better to be clear and thorough than consistent. Consistency gets you nothing, especially if it is consistently bad.
> using plurals is not the only, and probably not the superior, solution.
Why?
> Whatever you do, putting "v1" in the middle of your URL is the wrong way to do it.
Why?
> Nesting resources is an anti-pattern that quickly creates a mess.
Why?
Edit: not sure why the downvotes. I'm genuinely interested, but the parent doesn't contain much useful content.
The plurals or not thing isn't a big deal. I really just object to the author picking one and claiming it's better with justification.
Putting "vi" in your URL decreases both readability and modularity. All things being equal, concise URLs are more readable. "v1" are extra characters without significant benefit. It also creates huge maintenance overhead. How many APIs do you think you can simultaneously maintain well? I am happy with one good one myself. Every extra new version you create (as opposed to gracefully improving the existing one) is more technical debt.
Let's take the nesting example: /artists/8/albums. What if you want to access an album by itself? You also need an /albums resource so you've just created two resources when you need only one. The /artists/8 response should include a list of albums that hyperlink to the /albums resources. If you absolutely have to have a clean list (without the artist header information, just filter it with a query string /albums/?artist=8. This accomplishes the same thing in a more predictable and consistent way without magic URL params. The major benefit of this type of design is it makes tracing execution from the interface to a code location much clearer by avoiding spaghetti URL routing.
> The plurals or not thing isn't a big deal. I really just object to the author picking one and claiming it's better with justification.
Agreed, I was annoyed by that as well when reading the article.
> Putting "vi" in your URL decreases both readability and modularity. All things being equal, concise URLs are more readable. "v1" are extra characters without significant benefit. It also creates huge maintenance overhead. How many APIs do you think you can simultaneously maintain well? I am happy with one good one myself. Every extra new version you create (as opposed to gracefully improving the existing one) is more technical debt.
It is true that versioning your API creates more maintenance, since you're supporting old versions of your code. However, it does make things more maintainable for users of your API. If you don't provide at least two versions, there is really no way to make a breaking change to your API without breaking your API clients. We have an API that is now up to version (IIRC) v1.13.4, where the first two components indicate breaking changes, and the last component is for additions. While the extra maintenance is noticeable (and we sometimes discuss how to decrease it) it's not huge, and very manageable. And it's helped us maintain our own internal tools, as well as upgrade different services that talk to each other using these APIs, but can't be upgraded simultaneously.
> Let's take the nesting example: /artists/8/albums. What if you want to access an album by itself? You also need an /albums resource so you've just created two resources when you need only one. The /artists/8 response should include a list of albums that hyperlink to the /albums resources. If you absolutely have to have a clean list (without the artist header information, just filter it with a query string /albums/?artist=8. This accomplishes the same thing in a more predictable and consistent way without magic URL params. The major benefit of this type of design is it makes tracing execution from the interface to a code location much clearer by avoiding spaghetti URL routing.
I can see this if you have lots of domain objects that are related more loosely. However, for objects that are more closely related (say, a blog post and its comments) I can also see the advantages of the nested structure, and you'll probably never request a certain comment without first knowing the post. On the other hand, perhaps you want the comments but relating to a user instead of a post...
How we've dealt with this is by mounting a sub-resource (comments, for example) on multiple parent resources (posts and users). This doesn't have to lead to complicated code if your abstractions are set up right. But I can definitely also see the advantages to a completely flat url structure. The more I think about it, the more I want to try this for a future API.
Eventually we'll all get to a point at which the generalization must stop. REST advocates think that point is much farther away than is commonly believed. In the case of my dumb example, giving the client developer a version number wouldn't really have helped her avoid a rewrite, because Widget A is no longer available and Widget B must be fizzgiggled before it is frobnobulated. You could imagine that she has enough pull to insist on treating her Widgets exactly as she pleases, but that's not the hypothesis here. (After all in that case she could just have her own entry URI.) It's much better to use media types, link relations, etc. to let the client implicitly learn the information it needs to know every time it needs to know it.
If you have actual paying customers that you'll need to support over many years then version your API. Paying customers won't tolerate API breakage and you can't always force them to update on your schedule. Assuming you still want to evolve the API and also sign up new customers, you'll quickly find out you'll need versioning.
http://datatracker.ietf.org/doc/draft-ietf-appsawg-http-prob...
Their example:
HTTP/1.1 403 Forbidden Content-Type: application/problem+json Content-Language: en
{
"type": "http://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "http://example.net/account/12345/msgs/abc",
"balance": 30,
"accounts": ["http://example.net/account/12345",
"http://example.net/account/67890"]
}
type, title, detail and instance are attributes defined by the spec. balance and accounts are extra attributes added for this error. I suppose that if I want to return validation errors to decorate an input form I'll have to add many custom attributes like those.AFAICT, This makes it makes it inapplicable to REST APIs that do not use basic or digest authentication, at least without violating the spec for the 401 response code.
Is there something that I've missed?
http://blog.mwaysolutions.com/2014/06/05/10-best-practices-f...
http://www.vinaysahni.com/best-practices-for-a-pragmatic-res...
The Github team does a pretty good job of incorporating modern best practices as well, so I often use their API as a reference: https://developer.github.com/v3/
One way to think of it is that status codes are part of the transport, and your own application logic (validation, application error conditions, warnings, etc.) should never use HTTP error codes.
A dumb proxy server should be able to cache any response (including its status code) on a GET or HEAD without needing to know about any application logic.
GET /products/ : will return the list of all products
POST /products/ : will add a product to the collection
GET /products/4/ : will retreive product #4
PATCH/PUT /products/4/ : will update product #4
POST /products/4/someCustomVerb : custom verb
Here are two of my favorite REST resources (pun intended).
Richardson Maturity Model: steps toward the glory of REST
http://martinfowler.com/articles/richardsonMaturityModel.htm...
RESTful Web Services Cookbook: Solutions for Improving Scalability and Simplicity
http://www.amazon.com/gp/product/0596801688
And I am looking forward to widespread adoption of the REST problem standard posted here a few weeks ago.
http://www.ietf.org/id/draft-ietf-appsawg-http-problem-00.tx...
I think this is actually quite debatable and I've seen a lot of people argue that nested resources are an anti-pattern. I only ever use nested resources myself when the child resource is existentially dependent on the parent.
GET /artist/8/albums
{ albums: [89, 93] }
GET /albums/89
{
album: {
id: 89,
title: 'Blah'
}
} GET /albums?artist=8
GET /albums?artist=8&artist=10
GET /albums?title='Blah'Do:
/artist/8/albums
/albums/9
Don't:
/artist/8/albums/9
Using query filters versus nesting are virtually synonyms. I would say there is a minor semantic distinction in that the first one is a definite relationship, and the second one is a possible relationship. That is, "get the albums for artist 8" versus "get the albums searching for artist 8". The search could include other parameters as well, making it not as definite.
/artist/8/albums
/albums?artist=8
/artist/{artist}/albums
/albums?artist={artist}
AlbumsController#index(artist)
By contrast, the reason why designing real REST services is hard is because you actually have to _design_ them. This requires long, hard thinking about the domain of the problem at hand, and as such, doesn't square well with our "agile" methodologies of week-in and week-out iterative hacking.
Much as I typically loathe self-promotion, I did give a talk on this recently that enumerates some design strategies: https://speakerdeck.com/nateabele/designing-hypermedia-apis -- check out slides 8-20.
401 - Unauthorized looks like the correct answer, but if you read the Wikipedia article 401 is specifically intended for HTTP Authentication using usernames and passwords set in the headers.
I recently ran into a situation where a third party library on receiving a 401 proceeded to then ask for HTTP credentials and try to resubmit the request when actually the server indicated that we had just submitted the wrong username/password for our login API (which doesn't even use HTTP Auth). We don't use WWW-Authenticate headers but the third party library seems to be following the standard.
So should we be returning 400 instead ?
403 Forbidden (or 404 Not Found if you don't want to leak information about the existence of a resource to unauthorized users) is probably the right one to use when the access is unauthorized in the general sense, but not the specific kind of HTTP Authentication issue that 401 addresses.
I think that in context "authorization" in 403 can only be understood to mean the same thing as is authorization is implied to mean by the use of "Unauthorized" with the specific definition in 401 -- that is, reauthentication via the HTTP authentication methods. Under that view, 403 (and, to avoid leaking information, 404) fits.
400 does not seem to fit: it is not a generic code that fits the whole class of things in the 4xx series. Its definition is specifically "The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications." But the problem that is being identified is not malformed syntax.
> Here are some bad examples :
> /retreiveClientByOrder?orderId=1
I note the author didn't go on to demonstrate a better way of doing this. What would he recommend, /clients?by_order_id=1 ? SELECT * FROM orders WHERE client_id = 1
And for
GET /clients/1/orders
it seems like in practice it would be the same relation since it would be wasteful to store two tables. Is this roughly correct? SELECT * FROM clients WHERE client_id IN (SELECT client_id FROM orders WHERE order_id = @order_id)
The GET /clients/1/orders is what would result in your query (for client 1 list all orders).REST manipulates resources but not every software service maps to resources, or (very) painfully so. This is easy to overlook when you have not had to implement a substantial service that is not a simple storage interface in this fashion. It might be tempting to write an article not trying to solve or even address this but it wrongly makes things appear more simple than they are.
REST often tries to map a graph of resources on a tree (the URL space). This problem is more related to the web and naming in general yet there are many possible solutions and no clear rule to apply, leaving plenty of room to blind alleys and time lost pondering which option is the least ugly. I'm not blaming REST here but this still is a major problem seldom addressed in articles.
REST, HATEOAS and friends lean a lot on the theory side seducing you into thinking machines will use your API without human intervention and make you lose time building for a non-existant use case (and your boss doesn't want to make automated access to his data that easy by the way). I suspect they will succeed at the exact same time the semantic web succeeds.
REST tries to convince you that everything will map cleanly to the HTTP standard, and it's pretty close, but most of times it falls short in a way or another.
In pratice most blog posts will tell you to use nouns, to rely on status codes, etc, yet every other popular API will derail in a way or another when faced with the cases that don't fit.
To sum it up, theory is cute, reality is less. Having a clean scheme where everything could theoretically fit is very seducing to any software engineer. In a way it feels like the holy grail, and it could be, but maybe it's not. And if it's not, trying to make everything fit in the wrong model could just be an awful waste of time. I still like the fact that it forces my brain to think in a non-intuitive way about some problems, but well. Our profession is plagued with micro-cults, holy grail models, silver bullets, magic blueprints we try to cast everything we can get our hands on in. MVC comes to mind. I think REST is becoming my second favorite.
If for some unknown reason you want to write APIs that don't go down faster than a 15 year old girl faints upon stumbling onto a boy from 1D in a local McDonalds you should:
a) use verbs
b) separate heavy end point from light end points
c) make URL easy to parse by load balancers and proxies
If you do it like this, how do you then deal with 1.0.1? Especially in a framework like rails, where paths basically map to a folder structure?
I agree it's much nicer to be able to test manually when you have the version in the path but it significantly reduces flexibility later on.
If you need to, then it's the right moment to switch to v2.
If you need a breaking change, that's time to increment the major number. Besides that, who'd want to support that many versions running live?
This is key for modern services.
...really Twitter?
Was superseded by the RFC standard 429 in API version 1.1.
http://www.vinaysahni.com/best-practices-for-a-pragmatic-res...
api.com/steakejjs/v1/
This way, user's of your API can implement Content-Security-Policy in a secure manner (where an attacker can't use your 3rd party API to exfiltrate data). It's not like there aren't other ways to exfiltrate data, but this will definitely help.