I don't think GETs should ever change state. I'm fine with all other operations being POSTs though. If nothing else it provides compatibility with clients that don't support all the HTTP verbs (yes there are some)
By query, are you referring to the querystring/url size?
Practically speaking, I don't know if I've ever had a querystring that was effectively too large, busting some browser-determined limit. If you did, you might as well use a POST instead of GET, because the request is unlikely to be cacheable (I'm assuming the reason its such a large string is that you're serializing a large form of values or using the querystring to persist state in some way [protip: this is a bad idea]), which is the main reason to prefer GET for the request. POST (according to HTTP semantics, may have side effects, but is not required to have side effects).
IMHO, the choice between HTTP verbs beyond GET vs everything else is mostly bikeshedding. As a convention its fine, but there aren't a lot of pragmatic technical reasons to go with one over the other (referring to PUT vs PATCH vs POST), despite the HTTP semantics.
Usually used for long running queries but sometimes appropriate for this problem is creating a "query" resource via POST after which you have a URI for the results:
POST /queries
{"query": "..."}
201 Created
Location: /queries/1001
GET the results:
GET /queries/1001
{"results": ...}
You could optionally return results in the POST response too but I'm unsure whether that strictly conforms to the HTTP spec or not.
Don't let GETs edit data, if you use PUT make sure it's idempotent, DELETE looks dangerous, be sure not to waste that, and do whatever you want with POST.
No kidding. The debate here is a pretty funny. Make things as RESTful as you can and, by all means add additional verbs where necessary (cancel, empty, etc). The point is for your API to be easy to understand and to use by making it more like human language.
As REST is an architectural style I always preferred the phrase mock-REST, as in mock-tudor which is a physical world architectural style with similar meaning i.e. the house wasn't built with adherence to the tudor methods of architecture, but carries the surface benefits of the tudor architectural style.
I made the joke in my last job that REST actually stands for Reinvented Every Single Time, because we were working on our API and every bit of advice we read on REST principals seemed to either contradict or disagree with others.
In the end we made the API as REST(ful|ish) as possible and in places that we needed to be a little more flexible we tried to keep close to common practices. I think as long as your API is sane, easy to use, well documented (and tested), then users aren't going to care whether or not it is 100% RESTful.
I started developing network apps before REST existed -- probably like many people here, that wasn't long ago, SOAP, various things like RMI and then XMLRPC were things. SOAP was never good anyway, deeply buried in standards committee goo. But there are still things I miss from these things. When I found XMLRPC after doing all these things, it was very much a "WOW" moment. (JSON of course, with it's definite differences between maps/hash-tables and lists, is greatly superior to me).
A generic problem with REST APIs is they all handle collections, associating items with subcollections (including establishing and removing 1-to-many or many-to-many relationships between existing objects), query strings, authentication, and pagination very very differently.
Not all APIs are discoverable either, many don't do structured error codes. Thus to talk to one, rather than just using client-library, more work has to be done, often repeated work in multiple languages. Lots of REST APIs aren't well discoverable and rely on special logic to form up URLs, and many have weird verb pollutions - modelling a long running job for instance, I've typically have done as posting a job descriptor to a job collection, because the standard verbs don't really apply.
All being said, I prefer a nice broweseable REST API, but despite the accursed "XML" in the name, XMLRPC was easy - there were bindings in multiple languages and it was easy to ask an API what methods were supported. Problems came in the undefined parts - like whether "None" could be passed, and so on.
I can design and build some very elegant REST APIs, but the clients DO have work to do, every time. A good example for me was trying to write to GitHub's API, and then being angry at the way pagination was overcomplicated and URLs were not discoverable. (It might have gotten better).
BTW, if you are doing Python and want a GREAT foundation in pagination, discoverability, and so on, I recommend Django REST framework. One catch is you may wish to extend some of the serializers to return URLs relative to other URLs.
I don't think RPC is evil so much - over HTTPS and backed by a good webserver, and done so that it's stateless (something a pre-forking webserver (esp with MaxRequestsPerChild in play in Apache) forces you into, not so much REST protocols all by itself), I think it's just not socially acceptable.
So statelessness good, having to write client-specific "flavors" of REST, well, it's just reality.
(In other news, I'm disappointed all my He-Man figures got sold in the 80s so I can't illustrate tech cartoons with them, well done)
> SOAP was never good anyway, deeply buried in standards committee goo.
IMO SOAP in its very early days was actually fairly pleasant, at least when compared to the existing alternatives (things like COM and CORBA, which, ew). XML-RPC was also nice, in a "keep it simple, stupid" kind of way.
Then of course SOAP crushed XML-RPC, the crew of the USS Enterprise got their hands on it, and the rest is (depressing) history.
I've met SOAP when IBM was already pushing it, thus I may have completely missed the early days.
But I never even imagined I'd hear somebody say SOAP was more pleasant than CORBA. Yes, working with is CORBA barely better than hitting your foot several times with a hammer, but relative to SOAP, it's a breeze.
Anyway, it's kind of depressing that even now the best RPC we have to show is REST. It's a problem that looks so simple from a distance, why can't somebody build something really great here?
Yar, in my limited experience with SOAP, it's like Java: Good ideas under the hood, but then the usage you usually see is just /terrible/....
But I really like the idea that the API can tell you about the API, and do kind of wish JSON REST APIs had similar patterns.
I think the main problem that XML runs into is that it's used a data interchange format and/or a data serialization, instead of a markup.
I think the bit you're missing from the XML APIs - that makes you re-implement things - is the lack of an API descriptive document (like the WSDL). If that was a thing, REST is at least as automatically ported as any XML API style. (Someone would still have to write the libraries that turn the document into objects/functions, but that happens with the XML stuff as well)
But REST is RPC. I've read the article and the author basically defines RPC as a HTTP API that doesn't use the HTTP methods in a semantically correct manner but that's not what RPC is. RPC is any remote procedure call. It doesn't even have to be HTTP-based. Message queues are an example of something that's not RPC.
I agree with you. Too many get carried away with REST and don't think beyond HTTP.
I do appreciate the author's work here, I think the author was trying to help people clarify that REST/RPC don't need to be exclusive and that is helpful. All too often we encounter developers who want to sound smart and cool and state that it is "this tech" or "that tech" or NOTHING!
At a higher level of abstraction, representational state transfer should have nothing to do with HTTP semantics. It just so happens that we attribute REST with being related to HTTP semantics. But you could do REST with a non-HTTP protocol, if you wanted, why not?
Similarly, you can use a non-HTTP protocol in any other kind of framework for network based communication that you wanted...
And it just so happens that RPC is exposing functional, encapsulated units of code via network protocols and TCP/UDP sockets.
I remember trying to write my own network protocols for fun before over TCP and UDP sockets. Simple things like an echo service or a simple client/server application protocol. Doing that helps give one context for REST, RPC, SMTP, FTP, and more - semantics, concepts and frameworks over network connectivity.
I actually prefer RPC. It's not very often I'm making a call to a server that I don't want to have complex logic behind. The REST paradigm doesn't fit that (though you can wedge it in).
REST GETs are fine for getters, and I generally like REST URLs because their prettier and don't have god-function smell like you get with SOAP.
But for commands, a POST with params to distinct URLs for each command works fine.
If you have a 1:1:1 relationship between database models, in-memory models and the REST endpoint, and the primary purpose of the API is to manipulate these entities, there's a reasonably strong stylistic benefit to REST style. Not all applications are like this, but many bread and butter CRUD apps are.
One point that didn't get addressed in this article is the use of HTTP status codes to indicate the result of a request. REST encourages proper use of status codes – 404 for a missing resource, 422 for invalid data, 201 for successful resource creation, etc. – further enhancing the predictability of the API. How does RPC handle status codes?
And yet still so many API developers don't get this, or don't know about it, or don't think it's important. Generic API errors are also pretty bad; a ton I've used will just throw a 400 (or 500) with no information on why.
Eh, sorta. Send an invalid body, say an unavailable product ID, or an invalid quantity. What error will you return? HTTP codes and REST might make sense for some simple scenarios (like managing files), but it breaks down fast otherwise. Shoehorning everything into the few codes HTTP has seems pointless.
> Send an invalid body, say an unavailable product ID, or an invalid quantity. What error will you return?
In this case the client has sent an invalid request so the response should be 400 Bad Request or 422 Invalid Data, with details of the error in the response body.
400, 422 (or even 404 if the product id was part of the resource URL). That's not shoehorning, that's using something which defines a crude yet semantically consistent granularity, that does not prevent having more detailed errors in the response body and/or additional headers. So I get a level of abstraction for free, increasing consistency in semantics and behaviour both inside my API and outside, easing debugging and allowing me to use off-the-shelf HTTP components (including curl) while leveraging common knowledge of the protocol across applications.
The pet peeve issue I have with RPC/HTTP APIs is that people keep reinventing HTTP on top of it, only badly (at which point they may as well use RPC/TCP). That's why I like REST/HTTP, because I can "reuse things" when the problem model fits well within that tool (and it very often does). If REST/HTTP becomes a constraint instead of an asset, then maybe one should not use either REST or HTTP, and I'm fine with it because that was not the tool for the job.
Not using HTTP codes is much, much worse. I've dealt with SOAP/RPC APIs that return nothing but 200, no matter what. The actual status is an english word in the response body (i.e. OK, ERROR, etc.) That is a nightmare to deal with because you have to manually decode each and every request instead of using a library to do the heavy lifting for you.
Sometimes I have questions on which HTTP status code to use, but most of the time its pretty clear. And if you stick to the official codes most client side libraries will just work without any drama at all. As a bonus, all of the intermediate processes (proxies, firewalls, CDNs, etc.) will work as well without any finagling on your part. :)
I prefer REST for mainly aesthetic reasons: the URLs are pretty, and in Rails I can handle different HTTP actions in the same method, which usually ends up being some clean code:
def index
if request.put?
update_stuff
end
# get/put render same response content
end
One of the unexpected benefits of intercooler.js has been that I can use REST-fully designed end points for my html-partial endpoints, and it all just "looks right", even though it isn't a traditional JSON API.
> If a user want to stop using your service, you’ll do this (not so obvious) call:
> DELETE /users/1234
No! It would be
DELETE /sessions/12345
or possibly
DELETE /users/1234/session
or even
DELETE /users/1234/sessions/3
in the case a user can have more than one concurrent different sessions (this is actually a fairly common case for the application we do were I work. We don't use http for this though).
Unless you actually want to permanently stop the user from using the system, in which case
A missing factor is fragility in the face of change.
RPC leads to fragile protocols. Adding arguments to a procedure or adding properties to a result can often break clients and in practice you update systems lock step.
HTTP can gracefully handle different API version requests to the same resource. REST clients are encouraged to take only what they need from the representation.
Also, I strongly disagree with the Totaling points section. Seems too "nice" to both sides.
I like how when building REST API servers and clients there are standard components that just works. The entire API in the same format means it is easy to write a DSL across the entire API configure each endpoint - such as row level and field level permissions, pagination, filtering. If you have a well designed RPC you have the same benefit, but except with REST - you can reuse someone else's work because the design is the same. It literally takes 20 seconds to change the /user/ endpoint so:
1. Non-authenticated users can create users, and see a list of users with details that are public.
2. Authenticated users can view their own public and private details and have read/write access to most fields except is_staff.
3. Staff users have full permissions for users that belong to the country they are managing.
4. Superusers have access to everything.
Without the benefit of DSLs this would take hours to write all the if/else statements and unit test them. It would be a nightmare to do the same for all your endpoints. I assume you can write some abstraction functions to use for all your RPC endpoints but it'd be easier to reuse a library from past projects that had the same REST API design.
Basically, after form submit errors your location bar still says /widgets or /widgets/1 rather than /widgets/new or /widgets/1/edit, so bookmarking that page, or "like"ing it, or Ctrl-L + <Enter>ing are all broken. I'd much prefer a redirect back to the correct URL.
Also the distinction between "create" and "update" can break the back button, if the user creates something, then clicks back to edit their submission (because submitting a second time will create a second thing, not update their original thing). That's not Rails so much as REST in general.
Not sure if I 100% understand, but it sounds like maybe you want to rescue the exceptions you can think of explicitly, then
redirect_to previous_thing and return
if @foo.save
flash[:success] = "Saved"
redirect_to foos_path
else
redirect_to new_foo_path
end
The standard pattern is to `render 'new'` rather than doing the latter redirect. So I'm complaining that my preferred way isn't "blessed" by the Rails community. Also you need a trick to keep @foo.errors in between requests and load it up in your #new method the second time around.
I might be behind on state of the art these days...but my current api has no GET requests, everything is a POST. So in that term, we are not restful.
We had a couple of problems with GET requests: all of our data ended up in the url (we have too much info that has to be passed, we stopped working on some browsers), and the data returned could be cached (which is a HUGE problem for us).
Now, POSTs can also be cached, but there are easy ways around it...you can do the same thing with a GET, but that means adding more information to the url.
Anyway, one we got to the point of forgoing all GET requests, we ended up just doing everything with a POST for simplicity.
I did the exact same thing in a project of mine. We're shifting away from that and put our data in cookies, so we can cache some of the things our API send out.
Yeah, REST is nice for some things, but for normal APIs, you're calling them from a programming language, so calling remote functions (RPC) is very similar conceptually to calling local functions. You might not be able to guess the paths as easily as REST(?) but then again trying to make things REST style doesn't always work out when the things don't allow all the REST verbs or don't fit into a hierarchy, etc.
For serving a filesystem over HTTP REST is great though. And all that caching stuff comes in handy.
From a practical API standpoint though, having two different encodings (GET in url with url parameter encoding, and POST with form encoded or JSON) is a pain and has caused a number of minor bugs and definitely extra work.
Using HTTP is basically a socket for JSON RPC style calls is I think the most straightforward route. In this you have one RPC per request, POST only, with a JSON request body and JSON response. If you use keep-alive it's similar to a socket but can go through some firewalls a bit easier, and has a built-in framing format and metadata thing. Also it works with existing log monitoring tools and frameworks.
Where 'action' is something a bit more descriptive than 'PUT' or 'DELETE' or whatever. Kind of like an object-oriented api... I'm still always dealing with resources, but I have custom actions for specific use cases.
This is my approach as well. Works very well with an event-sourcing model.
It is much easier to capture user intent with
POST /api/customer/1/change-address-due-to-move
{ "address_1": "...", "address_2": "...", ... }
than with:
PUT /api/customer/1
{ "address_1": "...", "address_2": "...", ... }
Also, GET /api/resource/action is nice place for a payload describing the expected inputs to the action. Link it all together with hypermedia and you really have something ;)
Believe others are coming around to this line of thought: ThoughtWorks included "REST without PUT" onto their technology radar earlier this year.
It isn't just a convention, the reasons for doing this are laid out in the HTTP 1.1 spec and assumed by servers, proxies, browsers, clients and developers.
For example if I hand someone an API with a URI that accepts a PUT they know they can safely retry PUTs to that endpoint because the server state will always end up the same.
there is nothing in the specification of the PUT verb that indicates it is meant only for complete replacement of an existing resource. in fact, the RFC specifically has a section describing the semantics of creation using PUT. therefore, either your stance is trivially falsified, or you were replying to me out of context, which is intellectually dishonest.
> The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
It is pretty clear to me that the spec says PUT completely replaces the state of a resource. So not just a convention but what the spec says.
BUT lets take it further. Lets say you do allow partial updates with a PUT. Can you guarantee that your resource's state will always be internally consistent?
Say you have two clients, both doing partial PUTs and do the following:
Client 1: GET /foo
Client 2: GET /foo
Client 1: PUT /foo {'bar': 1}
Client 2: PUT /foo {'baz': 2}
Is the foo resource is a consistent state? For some applications it could be but for many it won't be. And worse for some applications it may not be idempotent and a client's proxy is going to silently retry a PUT that isn't safe to do so.
So by allowing partial PUTs we're requiring the developer to consider all combinations a resource could be updated. They then need to communicate the valid combinations to any clients.
OR they can split the resource up finer grained resources, each one representing a valid PUT.
so since the post I replied to said that POST is for create, and PUT is for complete replacement, and you just indicated that PUT can be used in ways that the OP did not, and I objected to the OP's prescriptivism, you agree with me despite your stance of arguing with me about it.
Why not PATCH /api/customer/1 {"address_1": "...", "history": "moved", ...} (i.e. send your intent as a parameter that may not necessarily get saved in this resource)
Because now your client needs to know what parts of the object need to be updated when a customer moves, and explain to the server exactly what those changes should be; and the server has to know how to validate that the client made a valid set of changes to the customer object.
If you instead have the client tell the server what kind of change you want to make, and provide the parameters to the operation, the server can do everything that needs to be done and the client doesn't need to care.
By (mostly) adhering to REST patterns you get so much stuff for free. Other developers can quickly get up to speed quickly. Client libraries are easier to write. Things like Ember Data work out of the box. I agree that every now and then doing a POST to /logout is easier than doing a DELETE /access_token/23, but a consistent API is far more worth it.
the problem with HTTP REST verbs is that not everything can be (or should be) represented as a resource.
a simple example is a one-click payment + order action. you're creating multiple records in different tables - payment gateway transaction log, payment table, an order table, probably creating a customer record, sending email notification, logging a conversion, etc.
that sequence of actions does not adhere neatly to any HTTP verbs. it can be more clearly called "processorder" because it involves a lot more than creating an order record in a table. if you'd like, you can of course do POST /orders, but the nuance of what's happening is unnecessarily lost.
another example is a taking that order and marking it as "shipped". it is not a simple PATCH /orders/123 shipped=true. the front-end does not know all the fields that must be set in all the places on the backend. it is in fact a series of actions that take some data from the front, and some from the back and do a bunch of things that represent the setShipped() sequence.
HTTP verbs were designed for managing documents, for which they work well. They also happen to map well for direct db entries via CRUD. but trying to shoehorn them into all aspects of complex web apps is misguided. a true RPC is often what is necessary.
"Buy this" might create multiple records in different tables, but there is no requirement that one URL in a REST API corresponds directly to one record or one table. The REST API does not have to expose the entire sequence of under-the-hood actions. This does not somehow require RPC to address.
how would you differentiate a direct CRUD route with one that performs a lot of additional things?
PATCH /orders/123 shipped=1
what does this do? does it simply set a field or does it trigger a shipOrder() sequence that also sets that field? what if you need the ability to do both (eg: admin interface & customer frontend)?
I understand that in this case you can instead do something like:
POST /shipments order=123
but not everything has a record backing it that would yield to this pattern. the response to a POST is supposed to be a Location header of the created record, so in fact you do need some form of URI and record for the created shipment.
HTTP REST's multi-item and hierarchical item management are also very hacked-in and necessarily too chatty. You cannot return multiple Locations in a header, for example, when multiple records are created. Strict adherence to the purity of HTTP verbs and limits quickly degenerates into custom hackery above and beyond the RFCs for anything mildly complex.
> the response to a POST is supposed to be a Location header of the created record
The HTTP spec says otherwise:
The action performed by the POST method might not result in a
resource that can be identified by a URI. In this case, either 200
(OK) or 204 (No Content) is the appropriate response status,
depending on whether or not the response includes an entity that
describes the result.
> You cannot return multiple Locations in a header, for example, when multiple records are created.
Again the HTTP spec allows you to manage this (though not in the header):
10.2.2 201 Created
The request has been fulfilled and resulted in a new resource being
created. The newly created resource can be referenced by the URI(s)
returned in the entity of the response, with the most specific URI
for the resource given by a Location header field. The response
SHOULD include an entity containing a list of resource
characteristics and location(s) from which the user or user agent can
choose the one most appropriate.
but here is a perfect example of multiple ways to do the same thing. and the custom additions to HTTP REST begin: multiple locations in the body of the response. the fact that sometimes the headers are sufficient, but at other times, you have to just create your own API to fill in the missing functionality using the response bodies.
"HTTP REST's multi-item and hierarchical item management are also very hacked-in and necessarily too chatty. You cannot return multiple Locations in a header, for example, when multiple records are created."
a simple example is a one-click payment + order action
A user action doesn't have to correspond to a single API call. Your users single click could translate to multiple API calls.
Additionally, as others have already mentioned, a conceptual resource does not have to equal a database entry.
In an application (front and back end) there are probably three data models: whats in the database, the "resources" transferred over the API, and what the client has locally (in memory or disk or both) and these three don't necessarily have a 1:1 mapping. For example, in an application I'm working on, the client stores a transformed denormalised version of the resources that allows easy filtering/searching/sorting in the UI, the API resources are very regular semantic "things" and the database stores them in a way that is easy to index and perform access control checks on.
Using REST over HTTP certainly gets us a lot for free. But I think we must concede that some APIs somewhere, are not best represented as a small, fixed set of actions on "resources". So then the question becomes, for web APIs, when do the benefits of complying with REST principals get outweighed by the benefits of not?
I'm not arguing the merits or demerits of REST - just stating that the use case leeoniya outlined can be handled with REST, if you should wish to do so.
It would be silly to say that no API ever is not better represented as something else - for example, a bidirectional streaming API (running over, say, WebSockets?) is probably not a great fit for REST, but for request/response-based API's I do find that so far REST is really nice.
Some people say that actions or commands aren't nicely represented as resources, but personally I like the idea of POSTing to a command resource in order to tell the server to execute a command (and GET could be used to retrieve all outstanding commands, PUT to replace one, DELETE to cancel etc). Again, not requiring a 1:1 match between resource and database makes this possible.
However, even within the world of REST, people have different approaches, so at the end of the day, to each his own. Use what you feel is simplest and makes most sense.
a simple example is a one-click payment + order action
A user action doesn't have to correspond to a single API call. Your users single click could translate to multiple API calls.
Additionally, as others have already mentioned, a conceptual resource does not have to equal a database entry.
In an application (front and back end) there are probably three data models: whats in the database, the "resources" transferred over the API, and what the client has locally (in memory or disk or both) and these three don't necessarily have a 1:1 mapping. For example, in an application I'm working on, the client stores a transformed denormalised version of the resources that allows easy filtering/searching/sorting in the UI, the API resources are very regular semantic "things" and the database stores them in a way that is easy to index and perform access control checks on.
Sending money and transfer item are a create operation against one resource. The same resourse actually, called transfer. That records who transfers what to whom and how much. Thats exactly how it is done in banking.
One point of doing REST instead of RPC is because you shouldn't re-invent the wheel. HTTP already has verbs and identifiers, so why create another set of verbs (the RPC methods)? REST is embracing HTTP to its fullest, RPC[overHTTP] is "just" taking advantage of HTTP's ubiquity across platforms.
[Edit: I don't mind having a few RPC-style endpoints in a REST API. The world's not a perfect square and sometimes things just don't fit the resource-driven model well. But for example, for performing logins (something which I previously did via "POST /login"), I switched to doing a "POST /sessions", because that's what a login it is: adding a new session.]
>One point of doing REST instead of RPC is because you shouldn't re-invent the wheel. HTTP already has verbs and identifiers, so why create another set of verbs (the RPC methods)?
Because HTTP's verbs weren't created with arbitrary operations in mind, but for specific, HTTP-related tasks.
Hmm. Seems to me that this actually relates well to the object-oriented versus functional programming "debate" - REST deals with things (like OO), RPC deals with actions (like functional).
But, in my experience, most requests consist of a "thing path" - host, resource; and then some "function" - get, update, other. POST is then the '=' - it's still a function under the hood, but because of it's commonality and interaction with language, the syntax is a little special.
In which case (and this is what I see in the APIs I most like) "the right thing to do" is to combine them, where you have pure REST when you're interacting with the object, but use RPC style when you're interacting with the object's actions.
Let's say I have some machinery exposed through an API, you might do:
GET host.com/machines/1 -> {"machine":"mixer","state":"off"}
POST host.com/machines/1?state:on -> 200
because I'm interacting with its state. But if I need to interact with its functional actions:
POST host.com/machines/1/mix?substance1=h20&substance2=c02
it makes more sense to phrase it as an action. "I want you to start doing this". You could also phrase as a request for a state transition:
POST host.com/machines/1?state:mixing&substance1=h20&substance2=c02
but (to me) that seems way weirder, generally.
I've got to go, but I think the answers change you go from physical resources to virtual ones, say, things that process information -
GET host.com/stock_analyzer/6/analyze?ticker=GOOG
where you might control state variables regarding the analysis algorithms using a REST-style.
This seems to me to be a debate between equally usable technologies. The differences between REST and RPC are slight enough that it won't make a big difference which you go with. To spend too much time on this would be bike shedding.
In my experience, it's way easier to write client apps against a REST API.
If you look at frameworks like Backbone, you can basically create models/collections for a simple CRUD app just by adding some values to a declarative hash (URI, primary key, etc.). Because everything is so predictable, it's really easy to specify a default behavior.
Granted, you could certainly do something similar with an RPC API, but I still think it would likely be harder to generalize.
Many public apis are REST based but do have some RPC actions with url-based HTTP APIs. Sometimes it isn't either or.
For example an API that allows you to get users might also have a job resource or action to perform RPC jobs on the server from a manage api path or similar.
Is it correct to say that POST is not idempotent? Sometimes it is, and sometimes it isn't. Maybe it would be more accurate to say there's no guarantee that it's always idempotent.
POST is not idempotent. If you fill out a form, submit it, hit back, and submit again, if the form uses POST, each submission may be processed separately.
POST is used to create resources that don't already have identifiers. So, if you're repeatedly submitting that form, your request is creating distinct resources on the other end. If the resource already exists -- if it has an identifier -- you'd use (an unsafe, but idempotent) PUT to replace it.
I would argue REST wins on beauty, because it continues to follow the intent of a URL -- you can locate the resource based on the URL. In RPC, the query parameters break the URL concept a bit by including location data in the parameters rather than in the path.
Seems like you can easily convert, if you want positional parameters. ?id=1&foo=2 just becomes /1/2. I fail to see how that really matters from the final client or server code.
The OP has essentially used circular logic: RPC is as good as REST because I know how to use it to address the issues that REST addresses (which I doubt, incidentally).
This to me is like arguing that object-oriented programming isn't really any better than procedural programming because I know how to write well-structured procedural programs. This is completely beside the point, which is that procedural programming as a style tends toward balls-of-mud programs (to simplify things), and object-oriented techniques were conceived of in order to address the characteristics of procedural programming that are the cause of this tendency.
I view RESTful API programming in a similar vein: RPC also has negative tendencies (such as the creation of fragile protocols), and REST addresses many, if not all of those. Most of the time for more people, RESTful techniques will lead to better service and API design than will RPC, just like for most of the people most of the time, object-oriented programming will lead to better programs than will procedural programming.
I think Rest works best in dynamically typed languages as it can be a little less strict on format. I think in typed languages RPC could work out better as you can filter out bad requests quicker with a stricter format. I also think RPC tends to be more brittle to changes just like typed languages :)
123 comments
[ 3.0 ms ] story [ 188 ms ] threadPractically speaking, I don't know if I've ever had a querystring that was effectively too large, busting some browser-determined limit. If you did, you might as well use a POST instead of GET, because the request is unlikely to be cacheable (I'm assuming the reason its such a large string is that you're serializing a large form of values or using the querystring to persist state in some way [protip: this is a bad idea]), which is the main reason to prefer GET for the request. POST (according to HTTP semantics, may have side effects, but is not required to have side effects).
IMHO, the choice between HTTP verbs beyond GET vs everything else is mostly bikeshedding. As a convention its fine, but there aren't a lot of pragmatic technical reasons to go with one over the other (referring to PUT vs PATCH vs POST), despite the HTTP semantics.
Don't let GETs edit data, if you use PUT make sure it's idempotent, DELETE looks dangerous, be sure not to waste that, and do whatever you want with POST.
I like your approach because it avoids never ending debates.
In the end we made the API as REST(ful|ish) as possible and in places that we needed to be a little more flexible we tried to keep close to common practices. I think as long as your API is sane, easy to use, well documented (and tested), then users aren't going to care whether or not it is 100% RESTful.
A generic problem with REST APIs is they all handle collections, associating items with subcollections (including establishing and removing 1-to-many or many-to-many relationships between existing objects), query strings, authentication, and pagination very very differently. Not all APIs are discoverable either, many don't do structured error codes. Thus to talk to one, rather than just using client-library, more work has to be done, often repeated work in multiple languages. Lots of REST APIs aren't well discoverable and rely on special logic to form up URLs, and many have weird verb pollutions - modelling a long running job for instance, I've typically have done as posting a job descriptor to a job collection, because the standard verbs don't really apply.
All being said, I prefer a nice broweseable REST API, but despite the accursed "XML" in the name, XMLRPC was easy - there were bindings in multiple languages and it was easy to ask an API what methods were supported. Problems came in the undefined parts - like whether "None" could be passed, and so on.
I can design and build some very elegant REST APIs, but the clients DO have work to do, every time. A good example for me was trying to write to GitHub's API, and then being angry at the way pagination was overcomplicated and URLs were not discoverable. (It might have gotten better).
BTW, if you are doing Python and want a GREAT foundation in pagination, discoverability, and so on, I recommend Django REST framework. One catch is you may wish to extend some of the serializers to return URLs relative to other URLs.
I don't think RPC is evil so much - over HTTPS and backed by a good webserver, and done so that it's stateless (something a pre-forking webserver (esp with MaxRequestsPerChild in play in Apache) forces you into, not so much REST protocols all by itself), I think it's just not socially acceptable.
So statelessness good, having to write client-specific "flavors" of REST, well, it's just reality.
(In other news, I'm disappointed all my He-Man figures got sold in the 80s so I can't illustrate tech cartoons with them, well done)
IMO SOAP in its very early days was actually fairly pleasant, at least when compared to the existing alternatives (things like COM and CORBA, which, ew). XML-RPC was also nice, in a "keep it simple, stupid" kind of way.
Then of course SOAP crushed XML-RPC, the crew of the USS Enterprise got their hands on it, and the rest is (depressing) history.
But I never even imagined I'd hear somebody say SOAP was more pleasant than CORBA. Yes, working with is CORBA barely better than hitting your foot several times with a hammer, but relative to SOAP, it's a breeze.
Anyway, it's kind of depressing that even now the best RPC we have to show is REST. It's a problem that looks so simple from a distance, why can't somebody build something really great here?
But I really like the idea that the API can tell you about the API, and do kind of wish JSON REST APIs had similar patterns.
I think the main problem that XML runs into is that it's used a data interchange format and/or a data serialization, instead of a markup.
I think the bit you're missing from the XML APIs - that makes you re-implement things - is the lack of an API descriptive document (like the WSDL). If that was a thing, REST is at least as automatically ported as any XML API style. (Someone would still have to write the libraries that turn the document into objects/functions, but that happens with the XML stuff as well)
I do appreciate the author's work here, I think the author was trying to help people clarify that REST/RPC don't need to be exclusive and that is helpful. All too often we encounter developers who want to sound smart and cool and state that it is "this tech" or "that tech" or NOTHING!
At a higher level of abstraction, representational state transfer should have nothing to do with HTTP semantics. It just so happens that we attribute REST with being related to HTTP semantics. But you could do REST with a non-HTTP protocol, if you wanted, why not?
Similarly, you can use a non-HTTP protocol in any other kind of framework for network based communication that you wanted...
And it just so happens that RPC is exposing functional, encapsulated units of code via network protocols and TCP/UDP sockets.
I remember trying to write my own network protocols for fun before over TCP and UDP sockets. Simple things like an echo service or a simple client/server application protocol. Doing that helps give one context for REST, RPC, SMTP, FTP, and more - semantics, concepts and frameworks over network connectivity.
The OSI model still matters. http://en.wikipedia.org/wiki/OSI_model
REST GETs are fine for getters, and I generally like REST URLs because their prettier and don't have god-function smell like you get with SOAP.
But for commands, a POST with params to distinct URLs for each command works fine.
Relevant: http://blogs.mulesoft.org/api-best-practices-response-handli...
In this case the client has sent an invalid request so the response should be 400 Bad Request or 422 Invalid Data, with details of the error in the response body.
The pet peeve issue I have with RPC/HTTP APIs is that people keep reinventing HTTP on top of it, only badly (at which point they may as well use RPC/TCP). That's why I like REST/HTTP, because I can "reuse things" when the problem model fits well within that tool (and it very often does). If REST/HTTP becomes a constraint instead of an asset, then maybe one should not use either REST or HTTP, and I'm fine with it because that was not the tool for the job.
This is a tool, not a religion.
Sometimes I have questions on which HTTP status code to use, but most of the time its pretty clear. And if you stick to the official codes most client side libraries will just work without any drama at all. As a bonus, all of the intermediate processes (proxies, firewalls, CDNs, etc.) will work as well without any finagling on your part. :)
> DELETE /users/1234
No! It would be
or possibly or even in the case a user can have more than one concurrent different sessions (this is actually a fairly common case for the application we do were I work. We don't use http for this though).Unless you actually want to permanently stop the user from using the system, in which case
would be the perfectly obvious choice.RPC leads to fragile protocols. Adding arguments to a procedure or adding properties to a result can often break clients and in practice you update systems lock step.
HTTP can gracefully handle different API version requests to the same resource. REST clients are encouraged to take only what they need from the representation.
Also, I strongly disagree with the Totaling points section. Seems too "nice" to both sides.
1. Non-authenticated users can create users, and see a list of users with details that are public.
2. Authenticated users can view their own public and private details and have read/write access to most fields except is_staff.
3. Staff users have full permissions for users that belong to the country they are managing.
4. Superusers have access to everything.
Without the benefit of DSLs this would take hours to write all the if/else statements and unit test them. It would be a nightmare to do the same for all your endpoints. I assume you can write some abstraction functions to use for all your RPC endpoints but it'd be easier to reuse a library from past projects that had the same REST API design.
Example:
Row level:
Field level:http://illuminatedcomputing.com/posts/2011/07/restless-doubt...
Basically, after form submit errors your location bar still says /widgets or /widgets/1 rather than /widgets/new or /widgets/1/edit, so bookmarking that page, or "like"ing it, or Ctrl-L + <Enter>ing are all broken. I'd much prefer a redirect back to the correct URL.
Also the distinction between "create" and "update" can break the back button, if the user creates something, then clicks back to edit their submission (because submitting a second time will create a second thing, not update their original thing). That's not Rails so much as REST in general.
We had a couple of problems with GET requests: all of our data ended up in the url (we have too much info that has to be passed, we stopped working on some browsers), and the data returned could be cached (which is a HUGE problem for us).
Now, POSTs can also be cached, but there are easy ways around it...you can do the same thing with a GET, but that means adding more information to the url.
Anyway, one we got to the point of forgoing all GET requests, we ended up just doing everything with a POST for simplicity.
For serving a filesystem over HTTP REST is great though. And all that caching stuff comes in handy.
From a practical API standpoint though, having two different encodings (GET in url with url parameter encoding, and POST with form encoded or JSON) is a pain and has caused a number of minor bugs and definitely extra work.
Using HTTP is basically a socket for JSON RPC style calls is I think the most straightforward route. In this you have one RPC per request, POST only, with a JSON request body and JSON response. If you use keep-alive it's similar to a socket but can go through some firewalls a bit easier, and has a built-in framing format and metadata thing. Also it works with existing log monitoring tools and frameworks.
GET /api/resource
POST /api/resource/action
Where 'action' is something a bit more descriptive than 'PUT' or 'DELETE' or whatever. Kind of like an object-oriented api... I'm still always dealing with resources, but I have custom actions for specific use cases.
It is much easier to capture user intent with POST /api/customer/1/change-address-due-to-move { "address_1": "...", "address_2": "...", ... }
than with: PUT /api/customer/1 { "address_1": "...", "address_2": "...", ... }
Also, GET /api/resource/action is nice place for a payload describing the expected inputs to the action. Link it all together with hypermedia and you really have something ;)
Believe others are coming around to this line of thought: ThoughtWorks included "REST without PUT" onto their technology radar earlier this year.
For example if I hand someone an API with a URI that accepts a PUT they know they can safely retry PUTs to that endpoint because the server state will always end up the same.
https://tools.ietf.org/html/rfc7231#section-4.3.4
So PUT either creates or replaces a resource.
Definition of replaced:
> 1. take the place of.
Source: https://www.google.com.au/search?q=define%3A+replaced
It is pretty clear to me that the spec says PUT completely replaces the state of a resource. So not just a convention but what the spec says.
BUT lets take it further. Lets say you do allow partial updates with a PUT. Can you guarantee that your resource's state will always be internally consistent?
Say you have two clients, both doing partial PUTs and do the following:
Is the foo resource is a consistent state? For some applications it could be but for many it won't be. And worse for some applications it may not be idempotent and a client's proxy is going to silently retry a PUT that isn't safe to do so.So by allowing partial PUTs we're requiring the developer to consider all combinations a resource could be updated. They then need to communicate the valid combinations to any clients.
OR they can split the resource up finer grained resources, each one representing a valid PUT.
If you instead have the client tell the server what kind of change you want to make, and provide the parameters to the operation, the server can do everything that needs to be done and the client doesn't need to care.
POST /api/resource;action
As that doesn't pollute the idea that the path itself leads to a resource.
By (mostly) adhering to REST patterns you get so much stuff for free. Other developers can quickly get up to speed quickly. Client libraries are easier to write. Things like Ember Data work out of the box. I agree that every now and then doing a POST to /logout is easier than doing a DELETE /access_token/23, but a consistent API is far more worth it.
a simple example is a one-click payment + order action. you're creating multiple records in different tables - payment gateway transaction log, payment table, an order table, probably creating a customer record, sending email notification, logging a conversion, etc.
that sequence of actions does not adhere neatly to any HTTP verbs. it can be more clearly called "processorder" because it involves a lot more than creating an order record in a table. if you'd like, you can of course do POST /orders, but the nuance of what's happening is unnecessarily lost.
another example is a taking that order and marking it as "shipped". it is not a simple PATCH /orders/123 shipped=true. the front-end does not know all the fields that must be set in all the places on the backend. it is in fact a series of actions that take some data from the front, and some from the back and do a bunch of things that represent the setShipped() sequence.
HTTP verbs were designed for managing documents, for which they work well. They also happen to map well for direct db entries via CRUD. but trying to shoehorn them into all aspects of complex web apps is misguided. a true RPC is often what is necessary.
PATCH /orders/123 shipped=1
what does this do? does it simply set a field or does it trigger a shipOrder() sequence that also sets that field? what if you need the ability to do both (eg: admin interface & customer frontend)?
I understand that in this case you can instead do something like:
POST /shipments order=123
but not everything has a record backing it that would yield to this pattern. the response to a POST is supposed to be a Location header of the created record, so in fact you do need some form of URI and record for the created shipment.
HTTP REST's multi-item and hierarchical item management are also very hacked-in and necessarily too chatty. You cannot return multiple Locations in a header, for example, when multiple records are created. Strict adherence to the purity of HTTP verbs and limits quickly degenerates into custom hackery above and beyond the RFCs for anything mildly complex.
> the response to a POST is supposed to be a Location header of the created record
The HTTP spec says otherwise:
> You cannot return multiple Locations in a header, for example, when multiple records are created.Again the HTTP spec allows you to manage this (though not in the header):
Source: http://tools.ietf.org/html/rfc2616edit: was quoting HTTP 1.0 rather than 1.1
but here is a perfect example of multiple ways to do the same thing. and the custom additions to HTTP REST begin: multiple locations in the body of the response. the fact that sometimes the headers are sufficient, but at other times, you have to just create your own API to fill in the missing functionality using the response bodies.
no me gusta.
So return the URI of a list of records. Easy.
A user action doesn't have to correspond to a single API call. Your users single click could translate to multiple API calls.
Additionally, as others have already mentioned, a conceptual resource does not have to equal a database entry.
In an application (front and back end) there are probably three data models: whats in the database, the "resources" transferred over the API, and what the client has locally (in memory or disk or both) and these three don't necessarily have a 1:1 mapping. For example, in an application I'm working on, the client stores a transformed denormalised version of the resources that allows easy filtering/searching/sorting in the UI, the API resources are very regular semantic "things" and the database stores them in a way that is easy to index and perform access control checks on.
It would be silly to say that no API ever is not better represented as something else - for example, a bidirectional streaming API (running over, say, WebSockets?) is probably not a great fit for REST, but for request/response-based API's I do find that so far REST is really nice.
Some people say that actions or commands aren't nicely represented as resources, but personally I like the idea of POSTing to a command resource in order to tell the server to execute a command (and GET could be used to retrieve all outstanding commands, PUT to replace one, DELETE to cancel etc). Again, not requiring a 1:1 match between resource and database makes this possible.
However, even within the world of REST, people have different approaches, so at the end of the day, to each his own. Use what you feel is simplest and makes most sense.
A user action doesn't have to correspond to a single API call. Your users single click could translate to multiple API calls.
Additionally, as others have already mentioned, a conceptual resource does not have to equal a database entry.
In an application (front and back end) there are probably three data models: whats in the database, the "resources" transferred over the API, and what the client has locally (in memory or disk or both) and these three don't necessarily have a 1:1 mapping. For example, in an application I'm working on, the client stores a transformed denormalised version of the resources that allows easy filtering/searching/sorting in the UI, the API resources are very regular semantic "things" and the database stores them in a way that is easy to index and perform access control checks on.
E.g. sending money, transfer item, bulk modify A while update B, etc.
[Edit: I don't mind having a few RPC-style endpoints in a REST API. The world's not a perfect square and sometimes things just don't fit the resource-driven model well. But for example, for performing logins (something which I previously did via "POST /login"), I switched to doing a "POST /sessions", because that's what a login it is: adding a new session.]
Because HTTP's verbs weren't created with arbitrary operations in mind, but for specific, HTTP-related tasks.
But, in my experience, most requests consist of a "thing path" - host, resource; and then some "function" - get, update, other. POST is then the '=' - it's still a function under the hood, but because of it's commonality and interaction with language, the syntax is a little special.
In which case (and this is what I see in the APIs I most like) "the right thing to do" is to combine them, where you have pure REST when you're interacting with the object, but use RPC style when you're interacting with the object's actions.
Let's say I have some machinery exposed through an API, you might do:
GET host.com/machines/1 -> {"machine":"mixer","state":"off"} POST host.com/machines/1?state:on -> 200
because I'm interacting with its state. But if I need to interact with its functional actions:
POST host.com/machines/1/mix?substance1=h20&substance2=c02
it makes more sense to phrase it as an action. "I want you to start doing this". You could also phrase as a request for a state transition: POST host.com/machines/1?state:mixing&substance1=h20&substance2=c02
but (to me) that seems way weirder, generally.
I've got to go, but I think the answers change you go from physical resources to virtual ones, say, things that process information -
GET host.com/stock_analyzer/6/analyze?ticker=GOOG
where you might control state variables regarding the analysis algorithms using a REST-style.
Thoughts?
I think it's the opposite: REST deals with data, while RPC calls an operation that has side effects on some (potentially) unknown state.
Not arguing that one is better just offering my thoughts on the analogy.
Emacs vs Vim
Destined to become one of the great debates of history.
If you look at frameworks like Backbone, you can basically create models/collections for a simple CRUD app just by adding some values to a declarative hash (URI, primary key, etc.). Because everything is so predictable, it's really easy to specify a default behavior.
Granted, you could certainly do something similar with an RPC API, but I still think it would likely be harder to generalize.
For example an API that allows you to get users might also have a job resource or action to perform RPC jobs on the server from a manage api path or similar.
This to me is like arguing that object-oriented programming isn't really any better than procedural programming because I know how to write well-structured procedural programs. This is completely beside the point, which is that procedural programming as a style tends toward balls-of-mud programs (to simplify things), and object-oriented techniques were conceived of in order to address the characteristics of procedural programming that are the cause of this tendency.
I view RESTful API programming in a similar vein: RPC also has negative tendencies (such as the creation of fragile protocols), and REST addresses many, if not all of those. Most of the time for more people, RESTful techniques will lead to better service and API design than will RPC, just like for most of the people most of the time, object-oriented programming will lead to better programs than will procedural programming.