3 ms·
> Your first instinct might be: “What if I return HTTP 201 Created immediately, but defer the actual creation to some later point?“... Well, you can’t do that.
by whack 8y ago
> Your first instinct might be: “What if I return HTTP 201 Created immediately, but defer the actual creation to some later point?“... Well, you can’t do that. If you do, you will be violating the HTTP/1.1: Semantics and Content protocol
> We know what status code to return, what about Location header? Simple. Instead of the location to the actual resource (/stars/97865), API will return location of the queued task that got created (/queue/12345)
> How to learn when resource is finally available? You need to query the queued task... Once resource is created, API should respond with 303 See Other status code on all the subsequent requests to the queued task... There are two alternative ways to deal with the temporary task resource: API client must issue DELETE request, so that server purges it. or, garbage collection can be a server’s job to do
I've always wondered about how important it is to follow REST conventions, at the cost of simplicity, when you control both the server and client software.
In the example given above, the recommendation to use a 202 instead of 201, sounds perfectly reasonable. However, creating and returning to the client a new queue resource, which returns a 303 when complete, and the client then has to delete... Is it really so bad to just return /stars/98765 immediately? And when queried, have the relevant GET API return a response indicating that construction of the resource is still in progress? If the client needs to wait for construction to complete before doing something else, can't it just poll /stars/98765 instead of /queue/12345?
More generally speaking, if you're designing an API for use by your own client, and you're facing a tradeoff between interface/implementation simplicity vs following the official REST protocol, is it really worth choosing the latter?
- diminoten 8y agoYou may control the client, but do you control the client library? If you want to get the most out of something like, say, Python's requests, following these conventions are your best bet.
- vfaronov 8y agoCase in point: CacheControl [1]. Plug it in and you get flexible caching — interoperable with NGINX, the browser, and everybody else — for very little. But it relies on the protocol. If you respond to GET /stars/98765 with 200 (OK) and an “under construction” placeholder, it’s going to get confused. [1] https://github.com/ionrock/cachecontrol https://github.com/ionrock/cachecontrol
- vfaronov 8y agoHTTP is an inherently complex protocol, which has over time accrued many idiosyncratic, non-orthogonal features to support various use cases of the growing Web. Just consider that there exists an entire class, entire design space of libraries known as “HTTP routers” which boil down to extracting arguments from the first line of an HTTP request. If you want simplicity, and you fully control both sides, and you don’t care about the systemic advantages that REST purports to provide, then your best bet is to avoid HTTP altogether (which in practical terms may of course mean tunneling through it) and stick to a simple, modern RPC protocol.
- drb91 8y ago> extracting arguments from the first line of an HTTP request. The reason this sounds simple is that the use of “arguments” conceals a good deal of semantics. Yes, you can cut a huge amount of complexity out by using a subset of HTTP, and I do recommend that, but by switching to a “modern” rpc protocol you also lose a good deal of introspection, low-effort ramp up for new contributors, and highly replicated semantics on server and client side. You can debug or interact with curl (or a number of similar tools), or a browser, or any virtually programming language with many choices for implementations. There are tons of commodity tooling for log parsing, playback inspection, testing, fuzzing, load balancing etc etc. You get a lot for “free”, and the potential complexity by itself is a poor excuse for dumping the baby out with the bath water. I also realize you may have acknowledged this by referencing “systemic” benefits, but I’d like to spell out just how large they are.
- geezerjay 8y ago> Just consider that there exists an entire class, entire design space of libraries known as “HTTP routers” which boil down to extracting arguments from the first line of an HTTP request. This comment sounds a bit disingenuous. Routing involves way more than extracting arguments from the first line of an HTTP request, but its complexity is not due to HTTP. Routing is based on content negotiation, and essentially everyone is free to design their own personal content negotiation process, and very often they do. Take, for example, content type. Do file extensions matter? Does the Content-Type header mean anything? If both are used what should prevail? What should the router do if none was passed? On top of that, then let's add HATEOAS, HAL, content type API versioning, custom headers, etc... In the end developers need to map HTTP requests to an action, and HTTP is not the problem. Libraries are helpful not because the problem is complex, but because ready-made solutions are better than rolling our own. There are plenty of libraries not because HTTP is complex, but because plenty of people have their personal preference.