I have a Web server that updates its data once per minute, and want to make that data available to clients of all types. In order to reduce bandwidth, I set up the PHP script to support conditional GETs, using IF-MODIFIED-SINCE and/or IF-NONE-MATCH. The idea is that clients can poll every 30 seconds and thereby be sure that they won't miss anything, but also won't get duplicate data.
That all works great for most types of clients, and I've verified that it works with clients that support the standard HTTP conditional GET semantics.
But it doesn't work with JavaScript because JSONP inserts a <script> tag into the DOM and lets the browser handle things--and there's no support (at least, none that I know of) for conditional GETs in <script> tags.
So I modified my PHP script to support passing an etag value. The returned data contains an etag value that's unique for that minute. When the JavaScript client receives data from the server, it saves the etag value so it can use that value in subsequent requests. The request takes the form:
http://api.mydomain.com/script.php?fmt=json&callback=jscallback&etag=ab79bc65e
If the etag of the data doesn't match the passed etag, then I send the new data.
This all works well and was surprisingly easy to code up using jQuery. My dilemma, though is what to do if the etag matches. I see two choices:
Return an HTTP 304 (Not Modified)
Return an HTTP 200 (OK), but with the returned data containing just the header information (modified date, etag, etc.) and no actual data items.
If I do the first, then the JavaScript client code is greatly simplified. The browser seems to work just fine if it gets a 304 response to an injected <script> tag. But ... something bothers me about this solution. I don't know what it is, but it seems like I'm depending on behavior that could be browser-specific. Some browser might decide to report an error if it gets a 304.
Doing the second would require a little bit more work on the server, slightly more bandwidth, and would require the clients to check the data to see if the data was updated. It's more work for everybody, but it seems cleaner.
So, to my question. If you were writing a JavaScript client to get this data, which would you prefer? A silent failure that never calls your "success" callback? Or a "success" return that has no data (beyond status) in it? A third option?
Absent any discussion from others, I went with my gut here and implemented the second option. The web server returns an HTTP 200, and the data contains a "Not Modified" status code along with header information, but no records. That makes the JavaScript just slightly more complicated, but prevents me from depending on undocumented behavior.
Related
I know that GET is used to retrieve data from the server without modifying anything. Whereas POST is used to add data. I won't get into PUT/PATCH, and assume that POST is always used to update and replace data.
The theory is nice, but in practice I have encountered many situations where my GET calls need to be replaced with POST calls. This is because the response often gets incorrectly cached. Where I work there are proxy servers for security, caching, load balancing, etc., and often times the response for GET calls is directly cached to speed up the call, whereas POST calls never get fully cached.
So for my question, if I have an API call /api/get_orders/month. Theoretically, this should be a GET call, however, the number of orders might update any second. So if I call this API at any moment it may return for example 1000, and calling it just two seconds later should return 1001. However, because of the cache, and although adding a version flag such as ?v=<date_as_int> should ensure that the updated value is returned, there seems to be some caches in the proxy servers that might ignore this.
Basically, I don't feel safe enough using GET unless I know for certain that the data will not be modified or if I know for a fact that the response is always the updated data.
So, would you recommend using POST/GET in the case of retrieving daily/monthly number of orders. And if GET, with all the different and complex layers and server set-ups, how can one be certain that the data is always updated?
If you're doing multiple GET request and something is caching the data in between, you have no idea what it is or how to change it's behavior then POST is a valid workaround.
In any normal situation you would take the time what sits in between your browser and your server, and if there's something that's behaving in a way that doesn't make sense, I would try to investigate and fix that.
So you work at a place where some of that infrastructure exists. Maybe talk to the people that maintain it? But if that's not an option and you just want to find the 'ignore every convention and make my request work'-workaround, then you can use POST.
I am designing my first REST API.
Suppose I have a (SOAP) web service that takes MyData1 and returns MyData2.
It is a pure function with no side effects, for example:
MyData2 myData2 = transform(MyData myData);
transform() does not change the state of the server. My question is, what REST call do I use? MyData can be large, so I will need to put it in the body of the request, so POST seems required. However, POST seems to be used only to change the server state and not return anything, which transform() is not doing. So POST might not be correct? Is there a specific REST technique to use for pure functions that take and return something, or should I just use POST, unload the response body, and not worry about it?
I think POST is the way to go here, because of the sheer fact that you need to pass data in the body. The GET method is used when you need to retrieve information (in the form of an entity), identified by the Request-URI. In short, that means that when processing a GET request, a server is only required to examine the Request-URI and Host header field, and nothing else.
See the pertinent section of the HTTP specification for details.
It is okay to use POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
It's not a great answer, but it's the right answer. The real issue here is that HTTP, which is a protocol for the transfer of documents over a network, isn't a great fit for document transformation.
If you imagine this idea on the web, how would it work? well, you'd click of a bunch of links to get to some web form, and that web form would allow you to specify the source data (including perhaps attaching a file), and then submitting the form would send everything to the server, and you'd get the transformed representation back as the response.
But - because of the payload, you would end up using POST, which means that general purpose components wouldn't have the data available to tell them that the request was safe.
You could look into the WebDav specifications to see if SEARCH or REPORT is a satisfactory fit -- every time I've looked into them for myself I've decided against using them (no, I don't want an HTTP file server).
Consider a call to a REST API:
POST /employees
[{ "name":"joe", "job":"dev",
{ "name":"bob" }]
For each array element an employee would be created. However, job is a required field, so the second element is invalid and the employee cannot be created.
What is a good response for this? 201 or 422?
I saw 207, but it seems to require an XML response, and the API does not use XML. It seems strange to return XML only for this case.
For this particular use case, I am thinking that all valid elements would be used to create resources. But I'm not sure what a good response would be.
We use 400 for any field validation errors (including missing required fields), be it on a single resource, or an entire collection.
I'm not entirely sure what are you trying to do.
Process only valid parts from the payload.
Don't process the payload at all.
In order for something to happen, the entire payload should be valid, not just parts of it. So I wouldn't process only the valid parts of the payload.
I would not use any 2xx status, because that would say to the user that everything worked OK, which isn't true in this situation.
I would not return a 400 status, because the syntax of the payload is syntactically correct JSON, but semantically erroneous.
That would leave us with a 422 status, which is more appropriate in this situation, because like I previously said, you have semantic not syntactic problems.
I'd stick with #visc advice, i.e., avoid batch processing. I have to say that #Alexandru Guzinschi advice on all or nothing approach despite being reasonable is not always feasable as sometimes you will become aware of one operation failure only after having tried it.
Both respose codes 207 and 422 you mentioned are defined as HTTP extensions for WebDAV, not in the protocol itself. And it's RFC (4918) is rather obsolete (that's why the suggestion of XML for the 207 response body).
Anyway, If you want to go down this road, I want to clarify that the use of XML is optional and you could create your own JSON definition. That would be harmless if you're not trying to implement a WebDAV server,
RFC 4918
"A Multi-Status response conveys information about multiple resources
in situations where multiple status codes might be appropriate. The
default Multi-Status response body is a text/xml or application/xml
HTTP entity with a 'multistatus' root element
One approach is to have a batch handler. So, you would send a batch of operations in a single HTTP request, but they are processed as individual operations against the api on the server. So, the batch response would include the appropriate response code for each individual operation.
A batch request can also include changesets to define transactional behavior.
Your batch could also include calls to different operations as necessary.
You don't state how you are building your api. If using ASP.NET Web API, there are batch handling capabilities available out of the box.
For a RESTful API that I'm creating, I need to have some functionality that get's a resource, but if it doesn't exist, creates it and then returns it. I don't think this should be the default behaviour of a GET request. I could enable this functionality on a certain parameter I give to the GET request, but it seems a little bit dirty.
The main point is that I want to do only one request for this, as these requests are gonna be done from mobile devices that potentially have a slow internet connection, so I want to limit the requests that need to be done as much as possible.
I'm not sure if this fits in the RESTful world, but if it doesn't, it will disappoint me, because it will mean I have to make a little hack on the REST idea.
Does anyone know of a RESTful way of doing this, or otherwise, a beatiful way that doesn't conflict with the REST idea?
Does the client need to provide any information as part of the creation? If so then you really need to separate out GET and POSTas otherwise you need to send that information with each GET and that will be very ugly.
If instead you are sending a GET without any additional information then there's no reason why the backend can't create the resource if it doesn't already exist prior to returning it. Depending on the amount of time it takes to create the resource you might want to think about going asynchronous and using 202 as per other answers, but that then means that your client has to handle (yet) another response code so it might be better off just waiting for the resource to be finalised and returned.
very simple:
Request: HEAD, examine response code: either 404 or 200. If you need the body, use GET.
It not available, perform a PUT or POST, the server should respond with 204 and the Location header with the URL of the newly created resource.
I need to send data and compare if it exists in the API server. For example:
$a['foo'] = 'hello';
$a['bar'] = 'world';
$rest->verb('resource', $a);
If the value of foo and bar exist in the API server it should return OK else Bad Request.
I would like to use GET as verb as it sounds more proper and just send data in query string but what if foo and bar is sensitive info and much more safer transmitted via post/put? But then I am not adding or updating anything.
What is the best verb in this situation?
Well, ruling out GET1 for security concerns effectively leaves only POST/PUT (flat out ignoring DELETE).
Out of these available options, I suggest using POST because it is the more common (especially outside of REST) and less specific HTTP verb overall.
From REST for the Rest of Us:
The POST verb can carry a variety of meanings. It's the Swiss Army Knife of HTTP verbs. For some resources, it may be used to alter the internal state. For others, its behavior may be that of a remote procedure call.
1 The issue with GET is that any data to the server must be transferred via URI (resource name and query string). This response thus assumes that a request using the POST verb would not use the URI to transfer sensitive information, or it would be no better than GET. The article How Secure are Query Strings over HTTPS? discusses some concerns with data in URIs, even with HTTPS connections (which should be used for all sensitive requests).
If you send a question like that to the server and get OK back. One millisecond later, it might not be OK any longer. So if you use an old (milliseconds old but still old) response from the server as truth to accept some client input, you still might go wrong when you try to store that data later on.
You should simply try to create something on the server, which means that it SHOULD be PUT or POST. If you read about REST, it states that PUT should be used if you know the resulting resource's URL and otherwise POST. There you have it. You probably want to send 201 if everything works and 409 otherwise.
What you create on the server with PUT / POST does not have to be the final data - it might just be a token that states that a client has claimed this id or whatever.
Now, if you still want your extra pre-check before storing anything at all on the server, you might want to look at Expect or Accept or something... dont quite remember. Here are your two friends when working with REST. :)
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
I also recommend this very good book on REST: http://shop.oreilly.com/product/9780596529260.do