HTTP response code for stale pagination - rest

I have a web service that runs a SQL query, sorted by one of several columns, and returns a single requested page (as in skip M limit N). The UI in front of it follows a 'load more' pattern, accumulating all loaded pages of results in one view.
The problem is new and deleted records, which can happen at any time, causing the result of a 'load more' to be wrongly aligned, and depending on the sort being used, even obscuring new records that should be shown. In addition to an automatic refresh on a timer in the frontend, I'm going to add a timestamp field to the RESTful request and response format to allow the webapp to detect that the view should be completely reloaded on a 'load more' call.
My question is, what HTTP status code is a best fit for this signal? In reviewing the codes I don't see an exact fit. I thought of using 302 Found with a link to 'page 1', but I wonder if that might cause unwanted caching of the redirect. I also thought of 400 Bad Request, but there's nothing actually wrong with the request, it's just the data needs to be reloaded.
Pages are served from a POST /path call where the requested page is provided in a JSON body.
I'm not a complete purist, so anything that would make it work without caching or other side effects is acceptable, but I would like to adhere to REST principles as much as possible.

anything that would make it work without caching or other side effects is acceptable
Responses to POST requests are not cacheable unless you explicitly mark them as such. So you can use any combination of status code, response headers and response entity to communicate the “please reload” message to the client.
You can use conditional requests. Include your client’s timestamp in the If-Unmodified-Since header. Respond with 412 Precondition Failed if client is stale. The client will have to know how to reload.
You can try 307 Temporary Redirect, but only if you encode pagination in /path, because upon receiving 307, (I’m assuming you’re doing AJAX here) XMLHttpRequest will transparently re-submit the same POST request to the new Location (at least this is what my Chromium does). Your actual page JSON will have to include metainformation on the range it covers, so that the client knows it has to replace the rows, not append them.

Related

RESTful API http method for a beforehead unknown method

I'm implementing a voting system (like/dislike) according to RESTful API and wondering what should I do if the intention is unknown while a request.
My real case:
If a user voting the first time - create a vote, if the user already has a vote - delete his vote (a vote can be only like or dislike, not 0). So what HTTP method and HTTP status code are suitable for this?
PUT sounds like a good option for this. PUT is used to create or replace the resource at the target uri.
PUT /article/[id]/myvote
When the vote is created, you can return 201. When it is overwritten, you can return 204 or 200.
My real case: If a user voting the first time - create a vote, if the user already has a vote - delete his vote (a vote can be only like or dislike, not 0).
How would you do it with a web site?
You would have some HTML page with a form on it; the form would include some input controls to collect information from the user. When the user submits the form, the browser would -- using the standardized HTML form processing rules, use the data and metadata of the form to create an application/x-www-form-urlencoded document, which it would send to the server as described by the form.
Supposing for this particular case that the action of voting is not "essentially read only", we would choose a form method that is not safe, which is to say POST.
The status codes to be returned would be exactly the same status codes (with the same meanings) that every other POST on the web uses. In particular, if the origin server successfully handles the request, then one of the 2xx status codes would be returned, with an appropriate entity and meta data.
If you aren't sure which 2xx code to use, 200 is the safe bet.
Remember, the world wide web is the reference implementation in the REST architectural style. You won't be far off if you storyboard a website, then use that to guide your api design.
There are other alternatives, that require a bit more thinking. One would be to treat the voter's ballot as a document that is stored on the origin server. The voter might GET a copy of his ballot, make local changes to it, and then request that the origin server apply those changes to its local copy of the ballot.
In that design, we would normally use PUT to copy our local edits to the web server; and the server would -- as before -- return some 2xx status code if request was successful.
The client, of course, will need to understand the representation of the ballot well enough to make the appropriate edits to it. You'll also need some sort of link convention that allows the client to find the right instance of ballot to edit.
The actual representation on the server doesn't need to be a document, of course. The document delivered to the origin server might instead be copied into rows in a relational database (an arbitrary example).
In the specific case of associating a representation (document) with a resource that previously didn't have one (in other words, if GET /ballot would have returned a 404), then the HTTP standard requires that you respond with a 201 status code, rather than a 200 status code, and include the appropriate metadata to identify the newly created resource.
GET /ballots/68D7165A-D172-4E32-84F3-E494A01B5C8E
404 Not Found
Ballot: /ballots/68D7165A-D172-4E32-84F3-E494A01B5C8E
has not yet been submitted
PUT /ballots/68D7165A-D172-4E32-84F3-E494A01B5C8E
Content-Type: text/plain
LIKE
201 Created
Location: /ballots/68D7165A-D172-4E32-84F3-E494A01B5C8E
Thank you for voting!
GET /ballots/68D7165A-D172-4E32-84F3-E494A01B5C8E
200 OK
Content-Type: text/plain
LIKE

GET or POST for stateless RESTFUL API

I'm writing a stateless API. You send it a document, it processes the document, and then returns the processed document. I'm struggling to understand how the RESTFUL rules apply. I'm not retrieving data, creating data or updating data on the server. There is no data on the server. What do I need to use in this case as the http method and why?
Good news - you are right that it is confusing.
Nothing on the server changes in response to the request. That suggests that the request is safe. So GET is the natural choice here... BUT -- GET doesn't support message payloads
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
HEAD, the other ubiquitous safe method, has the same problem (and is unsuitable when you want to return a document in any case).
The straight forward thing to do at this point is just use POST. It's important to realize that POST doesn't promise that a request is unsafe, only that it doesn't promise that it is safe -- generic components won't know that the request is safe, and won't be able to take advantage of that.
Another possibility is to look through the method registry, to see if somebody has already specified a method that has the semantics that you want. Candidates include SEARCH and REPORT, from the WebDAV specifications. My read of those specifications is that they don't actually have the right semantics for your case.
A Lot of ways to do what you want. But here is a small guideline.
I would create an endpoint that receives the document:
/receive_document
with a 'POST' method. Since you are 'sending' your document to the server
I would create an endpoint that serves up the processed document:
/processed_document
with a 'GET' method. Since you want to retrieve / see your document from the server?
The problem that you are trying to solve is mainly related to the document size, and processing time before returning the response.
Theorically, in order to use a restful approach, you have an endpoint, like yourhost.com/api/document-manager (it can be a php script, or whatever you are using as backend).
OK, so instead of naming the endpoint differently for each operation type, you just change the HTTP method, I'll try to make an example:
POST: used to upload the document, returns 200 OK when the upload is completed.
GET: returns the processed document, you can also return a different HTTP code, in case the document is not ready or even different if the document hasn't been uploaded. 204 no content or 412 precondition failed can be good candidates in case of unavailable document. I'm not sure about the 412, seems like it's returned when you pass a header in the request, that tells the server which resource to return. In your case, I think that the user processes one document at time. But to make a more solid api, maybe you can return an ID token to the user, into the POST response, then forward that token to the GET request, so the server will be able to know exactly which file the user is requesting.
PUT: this method should be used when updating a resource that has been already created with POST
DELETE: removes a resource, then return 204 or 404
OPTIONS: the response contains the allowed methods on this endpoint. You can use it to know for example which privileges has the currently logged user on a resource.
HEAD: is the same as a GET call, but it shouldn't return the response body. This is another good candidate for you to know when the document has been processed. You can upload with POST, then when the upload is done, start some kind of polling to the same endpoint with the HEAD method, finally when it will return "found", the polling will stop, and make the final GET call, which will start the download of the processed document.
HTTP methods are a neat way of managing HTTP communications, if used properly are the way to go, and easily understandable by other developers. And not to forget, you don't have to invent lots of different names for your endpoints, one is enough.
Hope that this helped you a little... But there are loads of guides on the net.
Bye!

HTTP Status-code for empty response and response not found

We are implementing a REST based web service and we have some queries on some of the use cases.
Consider there is a unique account which contains some information (Ex. added to cart information)
What response code should we return if no cart information exists (Ex. 0).
Our understanding was to return 200 with empty response.
User added cart information to his account, but cart is removed by admin.
What HTTP statuscode shall be used?
For situation 1 there are two options:
The cart is empty. I would return 200 OK returning an empty collection.
The cart doesn't exist. The correct case for this is 404.
For situation 2, it's really the same. The only potential difference is that if you returned 404 for situation 1, you could choose 410 gone, as it indicates that a cart was here before, but it's now gone.
Regardless of which you choose, I would recommend you take the same strategy for both situations. E.g.: Either return a 2xx code for both or a 4xx code for both.
If the admin deleted the cart by doing a DELETE request, then the 404/410 status codes are more appropriate.
See This Blog. It explains it very well.
Summary of the blog's comments on 204:
204 No Content is not terribly useful as a response code for a
browser (although according to the HTTP spec browsers do need to
understand it as a 'don't change the view' response code).
204 No Content is however, very useful for ajax web services which may want to indicate success without having to return
something. (Especially in cases like DELETE or POSTs that don't
require feedback).
The answer, therefore, to your question is use 404 in your case. 204 is a specialized reponse code that you shouldn't often return to a browser in response to a GET.
The other response codes are even less appropriate than 204 and 404.
200 should be returned with the body of whatever you successfully fetched. Not appropriate when the entity you're fetching doesn't exist.
202 is used when the server has begun work on an object but the object isn't fully ready yet. Certainly not the case here. You haven't begun, nor will you begin, construction of user 9 in response to a GET request. That breaks all sorts of rules.
400 is used in response to a poorly formatted HTTP request (for instance malformed http headers, incorrectly ordered segments, etc). This will almost certainly be handled by whatever framework you're using. You shouldn't have to deal with this unless you're writing your own server from scratch. Edit: Newer RFCs now allow for 400 to be used for semantically invalid requests.
Wikipedia's description of the HTTP status codes are particularly helpful. You can also see the definitions in the HTTP/1.1 RFC2616 document at www.w3.org

Requesting RESTful GET with meaningful Body? Standards not clear

We found ourselves in a dead end when trying to follow standards as we need to build a request that should be a GET and should have a meaning Body.
The request just wants to retrieve some data, no modification inside the database, just getting some data. But at the same time we need to send an array of ids for the objects we want to retrieve, and no, these objects can't be indexed in any way so we really need to send the list of ids or alternatively make 100 requests to the server to get them one by one. That's not gonna happen.
We could also add the list to the URL, but we can't be sure the URL won't end up being too long if the list of ids were to be too big. So to ensure the system doesn't fail we want to use the Body.
I read that a GET can have a Body, but only if it isn't meaningful:
HTTP GET with request body
Yes. In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in
mind. Server semantics for GET, however, are restricted such that a
body, if any, has no semantic meaning to the request. The requirements
on parsing are separate from the requirements on method semantics.
So, yes, you can send a body with GET, and no, it is never useful to do so.
This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).
....Roy
But our Body IS meaningful, which takes us to have to decide between unfollowing HTTP standards or unfollowing REST standards.
Is there any alternative to that? (It's not that this blocks us but I would like to know the answer).
Thank you very much.
you should consider changing your request to POST method.
As I understand it, there are three potential issues with a GET with request body: (link to blog)
Not all servers will support this.
Not all tools will support this (Swagger, POSTMAN added support this year: https://github.com/postmanlabs/postman-app-support/issues/131)
There is not yet a consensus on GET with request body. (For example, is Dropbox still using a POST)
so you'll have problems process the body with GET

How do you implement resource "edit" forms in a RESTful way?

We are trying to implement a REST API for an application we have now. We want to expose read/write capabilities for various resources using the REST API. How do we implement the "form" part of this? I get how to expose "read" of our data by creating RESTful URLs that essentially function as method calls and return the data:
GET /restapi/myobject?param=object-id-maybe
...and an XML document representing some data structure is returned. Fine.
But, normally, in a web application, an "edit" would involve two requests: one to load the current version of the resources and populate the form with that data, and one to post the modified data back.
But I don't get how you would do the same thing with HTTP methods that REST is sort of mapped to. It's a PUT, right? Can someone explain this?
(Additional consideration: The UI would be primarily done with AJAX)
--
Update: That definitely helps. But, I am still a bit confused about the server side? Obviously, I am not simply dealing with files here. On the server, the code that answers the requests should be filtering the request method to determine what to do with it? Is that the "switch" between reads and writes?
There are many different alternatives you can use. A good solution is provided at the microformats wiki and has also been referenced by the RESTful JSON crew. As close as you can get to a standard, really.
Operate on a Record
GET /people/1
return the first record
DELETE /people/1
destroy the first record
POST /people/1?_method=DELETE
alias for DELETE, to compensate for browser limitations
GET /people/1/edit
return a form to edit the first record
PUT /people/1
submit fields for updating the first record
POST /people/1?_method=PUT
alias for PUT, to compensate for browser limitations
I think you need to separate data services from web UI. When providing data services, a RESTful system is entirely appropriate, including the use of verbs that browsers can't support (like PUT and DELETE).
When describing a UI, I think most people confuse "RESTful" with "nice, predictable URLs". I wouldn't be all that worried about a purely RESTful URL syntax when you're describing web UI.
If you're submitting the data via plain HTML, you're restricted to doing a POST based form. The URI that the POST request is sent to should not be the URI for the resource being modified. You should either POST to a collection resource that ADDs a newly created resource each time (with the URI for the new resource in the Location header and a 202 status code) or POST to an updater resource that updates a resource with a supplied URI in the request's content (or custom header).
If you're using an XmlHttpRequest object, you can set the method to PUT and submit the data to the resource's URI. This can also work with empty forms if the server supplies a valid URI for the yet-nonexistent resource. The first PUT would create the resource (returning 202). Subsequent PUTs will either do nothing if it's the same data or modify the existing resource (in either case a 200 is returned unless an error occurs).
The load should just be a normal GET request, and the saving of new data should be a POST to the URL which currently has the data...
For example, load the current data from http://www.example.com/record/matt-s-example and then, change the data, and POST back to the same URL with the new data.
A PUT request could be used when creating a new record (i.e. PUT the data at a URL which doesn't currently exist), but in practice just POSTing is probably a better approach to get started with.