4 ms·
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
by leeoniya 11y ago
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.
- pekk 11y ago"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.
- leeoniya 11y agohow 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.
- hartror 11y agoI think some these statements aren't right: > 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. Source: http://tools.ietf.org/html/rfc2616 http://tools.ietf.org/html/rfc2616 edit: was quoting HTTP 1.0 rather than 1.1
- leeoniya 11y agothanks for the corrections. 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.
- Nemcue 11y ago"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." So return the URI of a list of records. Easy.
- dkersten 11y agoa 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.
- sopooneo 11y agoUsing 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?
- dkersten 11y agoI'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.
- dkersten 11y agoa 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.