Is it possible to cache the response of a Server to Server HTTP POST request? - rest

The purpose is to not trigger the request more than once at n days (for financial reasons) - the HTTP client should look into the cache to determine whether the response is already available. Will the max-age directive set to n days in the response help (e.g. Cache-Control: public, max-age=604800)?
I know this is available for GET requests with an enableCaching(ttl) option, but can we achieve similar behavior for POST requests?
To resume, my only idea is that if the response comes with an n day max-age directive set, this would force the service which makes the request to make another call after n days, no matter if it's a GET or POST.

Maybe Redis is that what you're looking for

You can request that POST responses get cached, but there are no promises. From [RFC 7231][1]:
Responses to POST requests are only cacheable when they include
explicit freshness information (see Section 4.2.1 of [RFC7234]).
However, POST caching is not widely implemented.
If you control both the server an the client, you can:
For cases where an
origin server wishes the client to be able to cache the result of a
POST in a way that can be reused by a later GET, the origin server
MAY send a 200 (OK) response containing the result and a
Content-Location header field that has the same value as the POST's
effective request URI (Section 3.1.4.2).
Also, note that any cache could clear out your representation at any time, so just because you ask for something to stay cached doesn't mean it will. You're specifying a max age, not a guaranteed age.
[1]: https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3

Related

Recommended or not: Sending a JSON body via POST HTTP Request without modification

Is it recommended to send a JSON body via a POST HTTP Request which doesn't modify anything?
Based on the link below, a Get request is not recommended to have a body. Thus, the other way is the one above.
HTTP GET with request body
Example:
Get the list of users, or anything for that matter based on parameters.
Http GET example.com/users
Body
{
name:"John",
age:1,
... long list of parameters
}
Is it recommended to send a JSON body via a POST HTTP Request which doesn't modify anything?
The rule is that POST is the default; it should be used unless there is something better.
For a request with "effectively read only" semantics, you want to use GET instead of POST... if it works. The challenge can be those cases where the request-target (aka: the URI) gets long enough that you start running into 414 URI Too Long responses. If your identifier is long enough that general purpose components refuse to pass the request along, then it is not something better, and you fall back to POST.
An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain. (HTTP Semantics, 9.3.1)
In other words, introducing a private agreement to include content in a GET request trades away inter-op, which - if you want "web scale" - is not a winning trade. So GET-with-a-body is not better, and you fall back to POST.
The HTTP working group has been working on semantics for a new "effectively-read-only-with-a-body" method token, which could prove to be an alternative for requests where you need to include a bunch of information in the body because it is too long to encode it into the URI. But we don't have a standard for that today, which means that it is not something better, and you fall back to POST.

Http Status for partial response in the case where API makes calls to multiple APIs

I have an API whose job is to aggregate resources obtained by calling multiple other APIs and then give out the aggregated response to the client. Currently even if one or more dependent API calls fail, I go ahead and aggregate response from the other dependent APIs and then give them out to the client with a 2xx status. In case all of the dependent API calls fail, I still give out a 2xx with empty list.
In case one or more dependent API calls fail, I want to give out an indication to the client. I was thinking of using the HTTP code 206. What would be the best approach to handle this scenario. Is giving out a 206 with the names of the dependent services that failed to give out a 2xx as part of a header the correct approach. If yes, what should this header be called?
I was thinking of using the HTTP code 206.
I can't promise, but that seems like a very bad idea; see RFC 7233
The 206 (Partial Content) status code indicates that the server is successfully fulfilling a range request
If the client didn't send you a range request (see RFC 7233 for the specifics), then I don't think there is any benefit in answering as if it had. General-purpose components are likely to get confused.
As for what status code to use instead: the response code, like the headers, is meta data so that general purpose components can understand what is going on and provide intelligent assistance. The details of what you are doing, that are to be understood by the bespoke client, belong in the response body.
(Analogy - on the web, the status code and the headers are for the (general purpose) browser. The response body is for the human being.)
200 OK is probably what you want to be using here; with a "representation of the status of the action" in the payload.

What data is cached by web proxy server(or other http caches)?

I am specifically interested in whether a proxy server(or other http caches) caches the URI, Method, Headers and Body of the client's request? Or is it only URI and Method?
The reason is I am confused with negative caching, e.g. caching response with 400 status code ("Bad request"). I mean if the first response had an "invalid" body that caused the 400 error and we cache it does it mean that subsequent requests with a "valid" body will still get 400 response from the cache? (Without even hitting the Origin server?
The GET requests are the ones that can be cached by intermediary caches.
As shown in the book "HTTP: The definitive guide" only URL and headers get cached.
The PUT, POST and DELETE requests will cause the cache to be invalidated as shown here.
So my original question (about 400 response because of invalid body) was wrong since GET request should not have body according to REST and other methods (which could have body) cause the cache to be invalidated.
Thanks #Adrien for pointing at it!

What HTTP code return when record is in inappropriate state?

I need to set particular resource accessible via REST Api to one of defined states - idle, running or stopped. How to inform a REST API client that record is already in requested state? E.g. client wants to start the record and that record is already running? He needs to know that record is running and operation is not processable.
It's definitively client error, so status code from 4xx family should be the answer. I have an idea to use 400, 409 or 412 but not sure.
There is "look-before-you-leap" technique that might be useful here.
You could insert If-Match header in your PUT (I assume its PUT) request
PUT /states HTTP/1.1
Host: www.example.com
Content-Type: text/plain
If-Match: "running"
Running
Either you get 200 or 412 (Precondition Failed).
How to inform a REST API client that record is already in requested state
Closest I could find is
409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.
emphasis mine
RFC 2616

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