Prevent an HTTP client from hitting a server with cache (iphone) - iphone

Ok, I'm confused. I'm trying to send back the magic headers from my server that will prevent a client from hitting the server again until a resource is stale.
I understand how ETag or Last-Modified works (Validation) - the client will ALWAYS still hit the server, and the server needs to validate the date or etag against the current value to know whether to bother serving up a new one.
Cache-Control and Expires, however, I don't think I understand. I've set the following:
Cache-Control: max-age=86400, must-revalidate
No matter what I do, my client (my browser, curl, NSURLConnection) always hits the server again on the second request. Is this a client thing? What headers should I send back to get the client to use it's private cache for a certain length of time?

As Nathan hints at in his answer, clients can issue a subsequent request with an If-Modified-Since header to determine whether or not their cache is stale. If the client receives a 304 Not Modified response, it will serve the content out of the local cache.
According to RFC 2616 (the HTTP 1.1 specification), the presence of must-revalidate within the Cache-control header forces clients to re-check their cache's status with the originating server prior to serving out of the cache.

For future reference - Mark Nottingham has written a great guide to HTTP caching:
http://www.mnot.net/cache_docs/#CACHE-CONTROL

The server needs to check the If-Modified-Since header and return a 304 not modified header if it wants the browser to keep caching.

Related

Cache-Control header to bust device cache but allow CDN

I am implementing an HTTP polling mechanism to detect device network status. I am planning to make a periodic GET request to a static file /static/byte.txt to validate the device's internet access.
I am using the Cache-Control: no-cache request header to make sure I am not served with a cached copy of the file on the device (which defeats the purpose). But I would like to still use any cached copy of the file on the CDN, as there is no need to download the file from the origin (my servers) every time. Does anyone know of a way to set the cache control headers to achieve that? Thanks!
The Cache-Control request header is a poor fit for this use case as both the client HTTP library and the CDN will assign the same meaning to whatever cache control directive you choose.
Instead, I recommend using a Cache-Control response header. In the response, you can use something like Cache-Control: max-age=0, s-maxage=604800, which indicates that the client should not cache the response but the CDN can cache it for up to a week (604,800 seconds).

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

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

HTTP Response for HP ALM Request is 302 instead of 200

I am using a Perl script with the
REST::Client module
to send requests to the HP Application Lifecycle Management (ALM).
The URL request works fine from a browser (giving 200 OK XML response), but requests from the program to retrieve defects from a project return 302 Found instead of 200 OK.
$client->GET($api_proto.'://'.$api_url.':'.$api_port.'/qcbin/rest/domains/my-domain/projects/my-project/defects/?login-form-required=y');
What's going wrong here?
If you're using HTTP then you should become familiar with the RFC which has this
302 Found
The requested resource resides temporarily under a different URI.
Since the redirection might be altered on occasion, the client SHOULD
continue to use the Request-URI for future requests. This response
is only cacheable if indicated by a Cache-Control or Expires header
field.
Now, referring to the documentation for
REST::Client, it says
# Requests can optionally automatically follow redirects and auth, defaults to
# false
$client->setFollow(1);
You will have to learn to read documentation if you intend to get anywhere on your own

Browser doesn't return If-None-Match header

i am trying to implement caching for dynamic API calls where data is near-static. The approach i have taken is using the ETag and returning an ETag header for a Web API response headers. However, Browser doesn't seems to return the "if-None-Match" header at all for me to validate the subsequent calls.
Please note that i am using https and i have a valid SSL installed. Anyone had this issue and potential clues?
Found the root cause of the issue, It was due to the wrong cache-headers being sent by the server particularly Cache-Control: no-store
After changing the response headers, Browser is now able to send the If-None-Match request header.
My current response header is as below which is good enough to request the browser to re-validate it.

What is the correct fallback if content negotiation fails?

What is the correct fallback if Content-Negotiation does not find a reasonable result due to a non 2xx status code? For example:
A client wants to download a PDF and sends following header Accept: application/pdf. Due to insufficient privileges the server would return a 403 Forbidden. You might want to explain the reason in more detail but it does not make much sense to return a PDF. How would you deal with that?
Should the server return an empty body? Should he ignore the Accept header and send some other representation like text/plain. Or is it the job of the client to provide alternatives per Accept: application/pdf, text/plain, */*.
Obviously if the user does not have permission to access the resource, there is no real alternative what a server can do. The server can however respond with content (even in an error case) which describes the error in more detail, if that response can be made using a media-type accepted by the client. The client should provide an Accept: header that describes all the media-types it can parse. So an automatic client would be able to do:
Accept: application/pdf, application/vnd.myapi.error
If content-negotiation fails, the returned code should be 406 Not Acceptable. The server can produce this if it can not provide any answer which would be acceptable to the client.
However, the specification states that the server may actually return an answer not explicitly acceptable by the client if it wants to, it is up to the client, to inspect the response headers to see what media-type the answer is.
Source: https://www.rfc-editor.org/rfc/rfc7231#section-3.4.1