How can a server handle HTTP requests in the order in which they were sent? - http

I'm building a simple CRUD application where there is a client, a server, and a database.
The client can send two types of requests to the server:
POST requests that update a row in the database.
GET requests that retrieve a row in the database.
One requirement of my application is that the requests have to be handled in the order in which they were sent from the client. For example, if the user makes a POST request to update row 1 in the database, then they make a GET request to retrieve row 1 in the database, the response to GET request must reflect the changes made by the previous POST request. One issue is that there is no guarantee that the server will receive the requests in the same order that the requests went sent. Therefore, in the example above, it is possible that the server might receive the GET request first, then the POST request later, which makes the response to the GET request not able to reflect the changes made by the previous POST request.
Another requirement of the application is that the client should not have to wait for the server's response before sending another request (this constraint is to allow for faster runtime). So in the example above, one possible solution is let the client wait for the server response to the POST request, and then it can send the GET request to retrieve the updated row. This solution is not desirable under this constraint.
My current solution is as follows:
Maintain a variable on the client that keeps track of the count of all the requests a user has sent so far. And then append this variable to the request body once the request is sent. So if the user makes a POST request first, the POST request's body will contain count=1, e.g. And then if they make a GET request, the GET request's body will contain count=2. This variable can be maintained using localStorage on the client, so it guarantees that the count variable accurately reflects the order in which the request was made.
On the server side, I create a new thread every time a new request is received. Let's say that this request has count=n. This thread is locked until the request that contains count=n-1 has been completed (by another thread). This ensures that the server also completes the requests in the order maintained by the count variable, which was the order in which the request was made in the client.
However, the problem with my current solution is that once the user clears their browsing data, localStorage will also be cleared. This results in the count getting reset to 0, which makes subsequent requests be placed in a weird order.
Is there any solution to this problem?

Related

What is the actual difference between the different HTTP request methods besides semantics?

I have read many discussions on this, such as the fact the PUT is idempotent and POST is not, etc. However, doesn't this ultimately depend on how the server is implemented? A developer can always build the backend server such that the PUT request is not idempotent and creates multiple records for multiple requests. A developer can also build an endpoint for a PUT request such that it acts like a DELETE request and deletes a record in the database.
So my question is, considering that we don't take into account any server side code, is there any real difference between the HTTP methods? For example, GET and POST have real differences in that you can't send a body using a GET request, but you can send a body using a POST request. Also, from my understanding, GET requests are usually cached by default in most browsers.
Are HTTP request methods anything more than just a logical structure (semantics) so that as developers we can "expect" a certain behavior based on the type of HTTP request we send?
You are right that most of the differences are on the semantic level, and if your components decide to assign other semantics, this will work as well. Unless there are components involved that you do not control (libraries, proxies, load balancers, etc).
For instance, some component might take advantage of the fact that PUT it idempotent and thus can re retried, while POST is not.
The Hypertext Transfer Protocol (HTTP) is designed to enable communications between clients and servers.
HTTP works as a request-response protocol between a client and server.
A web browser may be the client, and an application on a computer that hosts a web site may be the server.
Example: A client (browser) submits an HTTP request to the server; then the server returns a response to the client. The response contains status information about the request and may also contain the requested content.
HTTP Methods
GET
POST
PUT
HEAD
DELETE
PATCH
OPTIONS
The GET Method
GET is used to request data from a specified resource.
GET is one of the most common HTTP methods.
Note that the query string (name/value pairs) is sent in the URL of a GET request.
The POST Method
POST is used to send data to a server to create/update a resource.
The data sent to the server with POST is stored in the request body of the HTTP request.
POST is one of the most common HTTP methods.
The PUT Method
PUT is used to send data to a server to create/update a resource.
The difference between POST and PUT is that PUT requests are idempotent. That is, calling the same PUT request multiple times will always produce the same result. In contrast, calling a POST request repeatedly have side effects of creating the same resource multiple times.
The HEAD Method
HEAD is almost identical to GET, but without the response body.
In other words, if GET /users returns a list of users, then HEAD /users will make the same request but will not return the list of users.
HEAD requests are useful for checking what a GET request will return before actually making a GET request - like before downloading a large file or response body.
The DELETE Method
The DELETE method deletes the specified resource.
The OPTIONS Method
The OPTIONS method describes the communication options for the target resource.
src. w3schools

Why should a client state http method?

We know the difference between POST and GET, but why should a client state the method type when issuing http requests? Why should it make a difference for the server? in the end, it is the server job to deal with those requests according to their URL and Content. either by redirecting, blocking or accepting and using data (existing in the URL or request body).
An endpoint can accept both GET and POST requests (along with PUT, PATCH and DELETE). If the client does not explicitly state what type of request they are sending, the server will interpret it as a GET request (the default).
Consider the following PHP example, sitting on https://api.example.com/resources/:
<?php
if ($_POST["request"]) {
// Create new resource
}
else if ($_GET["request"]) {
// List existing resources
}
In both instances, the request parameter is sent to the same page, and different logic is run based on what the method is. But considering the same data is sent to the same page in both instances, the server wouldn't know which one of the two conditions to step into if the client doesn't explicitly specify the method.
In RESTful programming, both the client and server have been programmed to understand the request, but the client has no knowledge of the server itself. It is up to the server to process the request, based off of what the client asks it to do. And the client asks it to do different things by specifying the method.

Correct API approach for long processing time

I am making an HTTP web API that's mainly fed by a database. Simplified, the db contains userobjects.
These objects have a last_online (when the user was online) and last_checked (the last time I checked the userobject).
Checking the userobject can take from 3 to 30 seconds. When the last_checked time is less than 10 minutes then everything's okay; API call returns 200 and the userobject.
But I want to reprocess the userobject when the data is staler than 10 minutes. Obviously I can not have my API return sit there and wait.
What is the right approach to HTTP APIs that (sometimes) need to return data from long running processes?
My first proposal would be to have the server update the user object every X minutes as a background process. I don't see any reason to place the burden of keeping server data up-to-date on the client. Responses to the GET call would include an Expires header. The client could then cache the response for a fixed amount of time, saving you server hits until the data gets refreshed.
If you must make the refresh be client-driven, you want your GET to return a 202 Accepted, which indicates a valid request that the API is working on but has not completed. The entity that gets returned from your GET request should provide a timestamp for when the API should check back to get the updated data. Once the data has been refreshed, the GET will return a 200 Ok with the refreshed data. This is the approach I recommend.
GET /userObject
<- 202 Accepted
{ "checkAt": <timestamp> }
GET /userObject
<- 200 OK
{ "userName": "Bob", ... }
You could also consider using the Retry-After header in your response, but that's only appropriate for 503 Service Unavailable or any of the various 3xx (Redirection) responses. You definitely aren't describing a 503, and it doesn't sound like redirection is correct either.
If you do want to go the redirection route, you'd return a 302 Found, specifying the temporary URI in the Location header and the delay time in the Retry-After header.
A fourth approach would be to use a POST and the Post-Redirect-Get pattern. You could POST to your userObject URI and have it return the 302 Found with the Retry-After header.
I really don't think that options three or four buy you anything that the second option doesn't, and I think it's the most clear. Three implies that your resource currently lives in a different location when it doesn't. Four transforms what is fundamentally a GET request (give me the user object) into a POST (refresh the user object, but only if you need to).
If you do decide to follow #JonSkeet's suggestion, you probably want a separate resource, something like /userObjects and /userObjectRequests. The client would always POST to /userObjectRequests. If the userObject was valid on the back end, that POST would return a 302 to /userObjects. If it wasn't valid, the POST would return an entity with an id and an estimated completion time. The client could call GET on /userObjectRequests/{id}, and they'd either get a 302 to the userObject (if it's ready) or a 200 with the id and a new estimated completion time.
One fairly "old-school" way of handling this would be to return a continuation token - basically a job ID saying, "Check this periodically; sooner or later it'll come back with a result." Given that even 30 seconds is quite a long time, you might want to give back a continuation token even in the normal "checking" situation.
More modern alternatives would be web sockets or a hanging get... it really depends on what your client use cases are.

Network protocol for consistent mobile clients requests

Is there a protocol (or framework) that ensures that when a request fails, it fails on both the client side (iOS, Android, etc) and server side, and when it succeeds, successes on both sides?
The request might be completed on the server but because of dropped network connection, the client does not receive the response and thinks that the request failed.
The Post-Redirect-Get pattern can be adapted to this. The post part is used to submit the request, and the redirected get will be to a "results" page where the client can acquire the status (in progress, failure, success. etc).
Obviously, a client should not conclude from a network problem that the request failed. It should simply be prepared to wait and/or retry to obtain the status.
The interesting case is where the initial request submission is incomplete, i.e. nothing, not even the redirect comes back. This is where the adaptation comes in. The initial data submission should be after the server has generated a transaction identifier that the client can use as an alternative for status requests. (E.g., a form with a static field "Please save and use this tracking ID for status inquiries".)
If your question was whether this fallback can be automated at the protocol level, the answer unfortunately is no.

POST/Redirect/GET (PRG) vs. meaningful 2xx response codes

Since the POST request in a POST/Redirect/GET (PRG) pattern returns a redirect (303 See Other) status code on success, is it at all possible to inform the client of the specific flavour of success they are to enjoy (eg. OK, Created, Accepted, etc.) as well as any appropriate headers (eg. Location for a 201 Created, which might conflict with that of the redirect)?
Might it be appropriate, for example, to make the redirected GET respond with the proper response code & headers that would be expected from the POST response?
The HTTP 1.1 spec says:
This method [303] exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource.
But doesn't offer any insight into the loss of the more usual status code and headers.
Edit - An example:
A client sends POST request to /orders which creates a new resource at /orders/1.
If the server sends a 201 Created status with location: /orders/1, an automated client will be happy because it knows the resource was created, and it know where it is, but a human using a web browser will be unhappy, because they get the page /orders again, and if they refresh it they're going to send another order, which is unlikely to be what they want.
If the server sends a 303 See Other status with location: /orders/1 the human will be taken to their order, informed of its existence and state and will not be in danger of repeating it by accident. The automated client, though, won't be told explicitly of the resource's creation, it'll have to infer creation based on the location header. Furthermore, if the 303 redirects somewhere else (eg. /users/someusername/orders) the human may be well accomodated, but the automated client is left drastically uninformed.
My suggestion was to send 201 Created as the response to the redirected get request on the new resource, but the more I think about it, the less I like it (could be tricky to ensure only the creator receives the 201 and it shouldn't appear that the GET request created the resource).
What's the optimal response in this situation?
Send human-targetted information in the response body as HTML. Don't differentiate on the User-Agent header; if you also need to send bodies to machines, differentiate based upon the Accept request header.
If you have control over the web server, how about differentiating between the Agent header ?
Fill it in something only you know of (a GUID or other pseudo-random thing) and present that one to the webserver from the automated client. Then have the webserver response with 201 / 303 accordingly.

Resources