So this question has been asked numerous times in SO and elsewhere.
On SO this is probably the question with the most comprehensive answers and comments.
REST, HTTP DELETE and parameters
In my scenario I want to add information to a delete request, not to identify the resource, but as meta data. Specifically, just some additional data the delete operation should record in a log.
Based on everything I've read putting any parameters as part of the DELETE request goes against best practices. What would be the best practice in this scenario?
Metadata by its very name is data about a Resource. Using HTTP, such data belongs into HTTP headers.
Since the X- prefix is deprecated, just choose sensible header names for your metadata.
Related
So, I'm building a RESTful API, that's like a Parking system, it have ParkingLots and Cars that enter or leave ParkingLots, at this moment, my endpoints looks like this.
POST '/parking-lots' // To create a ParkingLot
POST '/cars' // To create a Car
But, how to name an endpoint that has EnterParkingLot or LeaveParkingLot feature following REST best pratices? I didn't found an article or blog post that answer this question so far.
But, how to name an endpoint that has EnterParkingLot or LeaveParkingLot feature following REST best pratices? I didn't found an article or blog post that answer this question so far.
The key abstraction of information in REST is a resource. Resources are generalizations of documents, not endpoints.
Useful work is a side effect of editing documents (Webber, 2011).
If you are having trouble figuring out the URI, that probably means that you haven't been thinking enough about the documents (aka you don't yet have a clear understanding of your "resource model").
One idea that can sometimes help is to think about a client with cached documents. When they send you one of these messages, which document in the cache is the most important one to invalidate?
In REST, it is normal (not necessarily common) to have a single resource handle many different kinds of edits. For instance, we might submit an EnterParkingLot form, that would update a parking lot resource, and then later submit a LeaveParkingLot form that updates the same parking lot resource (with the code on the server parsing the requests to distinguish the different kinds of edits).
But it would also be fine to add a "parking ticket" resource to your resource model, with a different ticket tracking the arrival and departure of each car.
Domain experts are typically good at telling you what the documents are, and what names make sense.
I would do it like:
POST '/parking-lot/$n/enter'
POST '/parking-lot/$n/leave'
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am trying to design a RESTful web API for mostly CRUD operations.
I have a design dilemma on how to model a save action for an entity which also can have optional side effects like updating other "child" entities that were not part of the original entity.
Example:
Template Entity
Child documents Entity
Template can have multiple child documents
If a template is updated, all or some of the children based on the entity can be updated.
GET /templates/{id} -> Returns template
POST /templates/ -> Creates template
PUT /templates/ -> Updates template
Now if we want to update template and also instruct the server to update all documents based on the template, what would be a good design?
1)
PUT /templates/
{
template: {
..
},
childDocumentsIds: [1, 3, 7...]
}
2)
PUT /templates?childDocumentIds=1,3,7
{
template
}
Similar questions has already been asked, but they do not quite answer my question:
How to design REST API for non-CRUD "commands" like activate and deactivate of a resource?
What RESTful HTTP request for executing actions on the server?
How to Route non-CRUD actions in a RESTful ASP.NET Web API?
I am trying to judge if other people have similar questions when designing REST APIs. Also lately after experience with few of them, I think we can do better than REST APIs.
I think we can do better than REST APIs.
The REST architectural constraints are designed with a particular problem in mind: "long-lived network-based applications that span multiple organizations." The reference application for REST is the world wide web. If that's not the kind of problem you have, then REST may not be the right fit.
HTTP is an application, whose application domain is the transfer of documents over a network. If you can frame your problem as document transfer over a network, then a whole bunch of the work has already been done for you, and you can leverage it if you are willing to conform to its constraints.
The remote authoring idioms in HTTP (primarily GET/PUT) are very crud like - please give me your latest representation of some document; here is my latest representation of some document, please make your copy look like mine. Our API is a facade -- we pretend to be a dumb document store that understands GET and PUT semantics, but behind the scenes we do useful work.
So we might have, for example, a simple todo list. At the beginning, it is empty
GET /todoList
200 OK
[]
And if we wanted to send an email to Bob, we would first edit our local copy of the document.
["Send an email to bob#example.org"]
And then we would ask the server to make its copy of the document look like our copy
PUT /todoList
["Send an email to bob#example.org"]
HTTP semantics tell the server how to interpret this message, but it gets to choose for itself what to do with it. The server might, for example, update it's own local copy of /todoList, send the email to Bob, update its representation of /recentlySentEmail, update its representation of /recentlySentEmailsToBob, and so on.
The response from the server takes a number of standard forms; 202 Accepted -- I understood your request, and I may do it later; 204 -- No Content -- I edited my copy of the document to match yours, here's some meta data; 200 OK -- I've made changes to my representation of the document, here they are (or alternatively, I've made changes to my copy of the document, you can ask me for a refreshed copy).
if we want to update template and also instruct the server to update all documents based on the template, what would be a good design?
The most straight forward example would be to just send the revised template, and allow the server to update other resources as it sees fit
GET /template
200 ....
[original representation of template]
// make edits
PUT /template
[revised representation of template]
200 OK
If the server knows which documents need to be updated, it can just update them. Ta-Da.
If the client needs to know which resources have been updated, just send that list back
PUT /template
[revised representation of template]
200 OK
[URI of resources changed by the template]
It can be a useful design exercise to work through how you might achieve the result using a web site. How might it go. You would GET a resource that includes a form; the form might include a text area with some string representation of a template. You would replace the representation in the form with the one you wanted, and submit the form, carrying the template to the server. It would make changes, then give you back a new form, with check boxes for the different resources that will be affected by the change, allowing you to perhaps change the default selections. You would submit that form, and then the server could make the appropriate changes.
That, right there, is REST -- because you are using standardized media types, general purpose components (like browsers) can do all of the HTTP and HTML book keeping. The browser knows how forms work, it knows how to take the form processing rules and meta data to create the appropriate requests. The web caches all know which representations can be stored, and which should be invalidated.
Im working on a web service that i want to be RESTful. I know about the CRUD way of doing things, but I have a few things that im not completly clear with. So this is the case:
I have a tracking service that collects some data in the browser (client) and then sends it off to the tracking server. There are 2 cases, one where the profile exists and one where it does not. Finally the service returns some elements that has to be injected to the DOM.
So basically i need 2 web services:
http://mydomain.tld/profiles/
http://mydomain.tld/elements/
Question 1:
Right now im only using GET, but im rewriting the server to support CRUD. So in that case i have to use POST if the profile does not exist. Something like http://mydomain.tld/profiles/ and then POST payload have the information to save. If the profile is existing i use PUT and http://mydomain.tld/profiles// and payload of PUT has data to save. All good, but problem is that as far as i understand, xmlhttp does not support PUT. Now is it ok to use POST even though its an update?
Question 2:
As said my service returns some elements to be injected into the DOM, when a track is made. Logically, to keep it RESTful, i guess that i would have to use POST/PUT to update the profile and then GET to get the elements to inject. But to save bandwidth and resources on the serverside, it makes more sense to return the elements with the POST/PUT to profiles, even though its a different resource. What are your take on this?
BR/Sune
EDIT:
Question 3:
In some cases i only want to update the profile and NOT receive back elements. Could i still use same resource and then using a payload parameter to specify if i want elements, e.g. "dont_receive_elements:true"
On question #1, are you sure that xmlhttp does not support "put"? I just ran http://www.mnot.net/javascript/xmlhttprequest/ on three browsers (Chrome, Firefox, IE) and according to the output, "put" was successful on all browsers. Following the information on http://www.slideshare.net/apigee/rest-design-webinar (and I highly recommend checking out the many Apigee videos and slideshows on restful API), "put" is recommended for the use case you mention.
But you may be able to avoid this issue entirely by thinking a little differently about your data. Is it possible to consider that you have a profile and that for each profile you have 0 or more sets of payload information? In this model the two cases are:
1. No profile exists, create profile with a POST on .../profiles/ Then add elements/tracking data with posts to .../profile/123/tracks/ (or .../profile/123/elements/)
2. Profile exists, just add the elements/tracking data
(Sorry without understanding your model in detail, it is hard to be very precise).
As for question #2 - going with a data model where a profile has 0 or more elements, you could update the profile (adding the necessary elements) and then return the updated profile (and its full graph of elements), saving you any additional gets.
More generally on question #2, as the developer of the API you have a fair amount of freedom in the REST world - if you are focused on making it easy and obvious for the consumers of your API then you are probably fine.
Bottom line: Check out www.apigee.com - they know much more than I.
#Richard - thanks alot for your links and feedback. The solution i came down to is to make the API simple and clean as you suggest in your comment, having seperate calls to each resouce.
Then to be able to save bandwidth and keep performance up, I made a "non-official" function in the API that works like a proxy internally and are called with a single GET, that updates a profile and returns an element. This, i know, is not very restful etc, but it handles my situation and is not part of the official API. The reason i need it to support GET for this i need to call it from javascript and cross domain.
I guess i could have solved the cross domain by using JSONP, but i would still have to make the API "unclean" :)
I have a REST service that serves Invoice functionality, for example I can create, update and delete an invoice via the REST service.
However I now need to have functionality to split an invoice into several new invoices, i.e. the method needs to create x invoices based on one invoice, and then delete the original invoice in one transaction.
I also need a merge method that does the opposite, i.e. multiple invoices merged into one.
How do I create such architect the RESTful way?
We had a similar issue where we wanted to merge 2 resources. After a long debate we decided that a consumer would POST a merge request resource which contained the 2 resources to be merged. Then after looking at it we decided that there was no need for both the complete source and target resource and instead a POST of just the unique identifier was sufficient. We didn't make the merge request with just the 2 ID's come in the body. It was easier to represent in a URL so that's what we did. The response from the POSTing of a merge request is the merged resource.
I guess I'm not a REST guru enough to tell you this was a good strategy or not, but for us it was a simple solution so we went with it.
When you say that want to implement this functionality in "one transaction" I assume you have already determined that you should combine generation of the new invoices and deletion of the old one, into one API call; which is the correct approach. With web services you do want to reduce chatter and there is probably some business logic on how this functionality will generate the new invoices and delete the old one. So I am assuming when you ask how to architect this in a RESTful way you are wondering which HTTP verb to use (i.e. GET, POST, PUT or DELETE) for this new API method. Usually these verbs map to CRUD type operations in the following manner:
Create -> POST
Read -> GET
Update -> PUT
Delete -> DELETE
So which verb to use when your function both creates and deletes records. A general rule with REST API's is if there is not a clear mapping to CRUD then use POST if there is a change to the server state and a GET if you are just returning information that does not change the server state. So in this case I would go with a POST.
If you are looking for additional guidance on architecting this please be more specific in what you are looking for and I will try to help.
I would do something like,
POST /InvoiceSplitter?sourceInvoiceId=99
and
POST /InvoiceMerger?sourceInvoiceIds=101,87,23,45
For a website I am working on defining a RESTful API. I believe I got it (mostly) correct using proper resource URIs and proper use of GET/POST/UPDATE/DELETE.
However there is one point where I can't quite figure out what the proper way to do it "in" REST would be - comparison of lists.
Let's say I have a bookstore and a customer can have a wishlist. The wishlist consists of books (their full Book record, i.e. name, synopsis, etc) and a full copy of the list exists on the client. What would be a good way to design the RESTful API to allow a client to query the correctness of its local wishlist (i.e. get to know what books have been added/removed on the wishlist on the server side)?
One option would be to just download the full wishlist from the server and compare it locally. However this is quite a large amount of data (due to the embedded content) and this is a mobile client with a low-bandwidth connection, so this would cause a lot of problems.
Another option would be to download not the whole wishlist (i.e. not including book infos) but only a list of the books' identifiers. This would be not much data (compared to the previous option) and the client could compare the lists locally. However to get the full book record for newly added books, a REST call would have to be made for every single new book. Again, as this is a mobile client with bad network connectivity, this could be problematic.
A third option and my favorite, would be that the client sends its list of identifiers to the server and the server compares it to the wishlist and returns what books were removed and the data for books that were added. This would mean a single roundtrip and only the necessary amount of data. As the wishlist size is estimated to be less than 100 entries, sending just the IDs would be a minimal amount of data (~0.5kb). However I don't know what kind of call would be appropriate - it can't be GET as we are sending data (and putting it all in the URL does not feel right), it can't be POST/UPDATE as we do not change anything on the server. Obviously it's not DELETE either.
How would you implement this third option?
Side-question: how would you solve this problem (i.e. why is option 3 stupid or what better, simple solutions may there be)?
Thank you.
P.S.: A fourth option would be to implement a more sophisticated protocol where the server keeps track of changes to the list (additions/deletes) and the client can e.g. query for changes based on a version identifier or simply a timestamp. However I like the third option better as implementation-wise it is much more simpler and less error-prone on both client and server.
There is nothing in HTTP that says that POST must update the server. People seem to forget the following line in RFC2616 regarding one use of POST:
Providing a block of data, such as the result of submitting a
form, to a data-handling process;
There is nothing wrong with taking your client side wishlist and POSTing to a resource whose sole purpose is to return a set of differences.
POST /Bookstore/WishlistComparisonEngine
The whole concept behind REST is that you leverage the power of the underlying HTTP protocol.
In this case there are two HTTP headers that can help you find out if the list on your mobile device is stale. An added benefit is that the client on your mobile device probably supports these headers natively, which means you won't have to add any client side code to implement them!
If-Modified-Since: check to see if the server's copy has been updated since your client first retrieved it
Etag: check to see if a unique identifier for your client's local copy matches that which is on the server. An easy way to generate the unique string required for ETags on your server is to just hash the service's text output using MD5.
You might try reading Mark Nottingham's excellent HTTP caching tutorial for information on how these headers work.
If you are using Rails 2.2 or greater, there is built in support for these headers.
Django 1.1 supports conditional view processing.
And this MIX video shows how to implement with ASP.Net MVC.
I think the key problems here are the definitions of Book and Wishlist, and where the authoritative copies of Wishlists are kept.
I'd attack the problem this way. First you have Books, which are keyed by ISBN number and have all the metadata describing the book (title, authors, description, publication date, pages, etc.) Then you have Wishlists, which are merely lists of ISBN numbers. You'll also have Customer and other resources.
You could name Book resources something like:
/book/{isbn}
and Wishlist resources:
/customer/{customer}/wishlist
assuming you have one wishlist per customer.
The authoritative Wishlists are on the server, and the client has a local cached copy. Likewise the authoritative Books are on the server, and the client has cached copies.
The Book representation could be, say, an XML document with the metadata. The Wishlist representation would be a list of Book resource names (and perhaps snippets of metadata). The Atom and RSS formats seem good fits for Wishlist representations.
So your client-server synchronization would go like this:
GET /customer/{customer}/wishlist
for ( each Book resource name /book/{isbn} in the wishlist )
GET /book/{isbn}
This is fully RESTful, and lets the client later on do PUT (to update a Wishlist) and DELETE (to delete it).
This synchronization would be pretty efficient on a wired connection, but since you're on a mobile you need to be more careful. As #marshally points out, HTTP 1.1 has a lot of optimization features. Do read that HTTP caching tutorial, and be sure to have your web server properly set Expires headers, ETags, etc. Then make sure the client has an HTTP cache. If your app were browser-based, you could leverage the browser cache. If you're rolling your own app, and can't find a caching library to use, you can write a really basic HTTP 1.1 cache that stores the returned representations in a database or in the file system. The cache entries would be indexed by resource names, and hold the expiration dates, entity tag numbers, etc. This cache might take a couple days or a week or two to write, but it is a general solution to your synchronization problems.
You can also consider using GZIP compression on the responses, as this cuts down the sizes by maybe 60%. All major browsers and servers support it, and there are client libraries you can use if your programming language doesn't already (Java has GzipInputStream, for instance).
If I strip out the domain-specific details from your question, here's what I get:
In your RESTful client-server application, the client stores a local copy of a large resource. Periodically, the client needs to check with the server to determine whether its copy of the resource is up-to-date.
marshally's suggestion is to use HTTP caching, which IMO is a good approach provided it can be done within your app's constraints (e.g., authentication system).
The downside is that if the resource is stale in any way, you'll be downloading the entire list, which sounds like it's not feasible in your situation.
Instead, how about re-evaluating the need to keep a local copy of the Wishlist in the first place:
How is your client currently using the local Wishlist?
If you had to, how would you replace the local copy with data fetched from the server?
What have you done to minimize your client's data requirements when building its Wishlist view(s) and executing business logic?
Your third alternative sounds nice, but I agree that it doesn't feel to RESTfull ...
Here's another suggestion that may or may not work: If you keep a version history of of your list, you could ask for updates since a specific version. This feels more like something that can be a GET operation. The version identifiers could either be simple version numbers (like in e.g. svn), or if you want to support branching or other non-linear history they could be some kind of checksums (like in e.g. monotone).
Disclaimer: I'm not an expert on REST philosophy or implementation by any means.
Edit: Did you ad that PS after I loaded the question? Or did I simply not read your question all the way through before writing an answer? Sorry. I still think the versioning might be a good idea, though.