I read Http spec. but I have a doubt and I hope someone can help me.
When a cache receives a request and has a stored response that must be validated (before being served to the received request), does the cache send the received request (adding the conditional header fields it needs for validation) to the next server OR does the cache generate a new request (with conditional header fields it needs for validation) and send the generated request to the next server?
Thank you very much! :)
I think the idea is that the client would issue the request with the key headers, and the server would either respond with the content or a 304 to use whatever was in the local cache.
This behavior should be the same for upstream caches along the network path all the way to the source of truth.
"When a cache receives a request..."
Cache doesn't receive HTTP request. It is user-agent (browser) that check cache to see whether there is any cache entry matched for an HTTP request. Cache itself is just a bunch of data stored in disk/memory.
"Does the cache send the received request...OR does the cache generate a new request..."
Cache doesn't send HTTP request. It is user-agent (browser)'s job to send the request.
In summary, cache is just bytes of data, it doesn't know when and where HTTP request is sent. All cache validation logic (cache related HTTP headers) is implemented by user-agent.
Related
If an application has client side caching, and data changes on server side, then how does client comes to know about it so that it can invalidate the cache?
If server send "Cache-Control: max-age=100" on response header after first action to get data from server then client save response data on local cache store.
If client send same request in about 100 seconds then response retrieved from local cache store and request dont send to server.
When pass over 100 seconds and send same request again to server, cache data will have been invalidate on local. Thus request arrive to server. If server recognize the request and decide to not modified on the source then do nothing and return response that's status is 304 (not modified).
Seeing this status, the client renews the validity period of the expired data and all requests they sent within 100 seconds are retrieved from the cache again.
This flow has client cache invalidate mechanism.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#Freshness
when the cache receives a request for a stale resource, it forwards this request with a If-None-Match to check if it is in fact still fresh. If so, the server returns a 304 (Not Modified) header without sending the body of the requested resource, saving some bandwidth.
Let's assume we have: a browser cache, proxy cache and an origin server:
The browser cache contains a stored stale resource with entity-tag "A".
The proxy cache contains a stored stale resource with entity-tag "B". The proxy cache can act as a client, and as a server.
This can for example be the case if you're just starting to use a proxy cache. What will happen in this case?
The browser will send a conditional request with If-None-Match: "A".
The proxy cache receives the conditional request.
The proxy cache will forward this request (according to the quote above). This is because the stored resource in proxy cache is stale.
The origin server receives the request with the entity-tag "A".
Let's say, the resource on the origin server contains entity-tag "A". Now the server will respond with a 304 Not Modified response.
At this point, I don't understand things anymore, so maybe I misunderstood something before? The 304 response is okay for the browser cache, because it contains the same resource as on the origin server (same entity-tag). However, the proxy cache contains an older resource (with a different Etag). If the proxy cache would receive the 304 response (and would update its metadata), then the proxy cache makes a resource valid again while it's an old resource.
This is not desirable, so probably I made a mistake somewhere? How does it actually work? How I have to see this process?
Have a look at the section 4.3 of the RFC7234 spec. Section 4.3.2 in particular says the following:
When a cache decides to revalidate its own stored responses for a
request that contains an If-None-Match list of entity-tags, the cache
MAY combine the received list with a list of entity-tags from its own
stored set of responses (fresh or stale) and send the union of the
two lists as a replacement If-None-Match header field value in the
forwarded request. If a stored response contains only partial
content, the cache MUST NOT include its entity-tag in the union
unless the request is for a range that would be fully satisfied by
that partial stored response. If the response to the forwarded
request is 304 (Not Modified) and has an ETag header field value with
an entity-tag that is not in the client's list, the cache MUST
generate a 200 (OK) response for the client by reusing its
corresponding stored response, as updated by the 304 response
metadata (Section 4.3.4).
So the proxy can send both entity tags (A and B) to the origin server for validation. If the resource representation hasn't changed, the origin server will send a 304 response. If the entity tag in that response is B, the proxy can freshen its stale, stored response and use it to send a 200 OK response to the client. Upon receiving this new response, the browser can update its cache with it.
Now, in the scenario you have specified, the 304 NOT MODIFIED response contains the entity tag A (can such a scenario even occur, given that you are accessing the resources through the proxy?). The spec doesn't seem to address this specific case explicitly, but I guess you can just forward the 304 NOT MODIFIED response to the browser. Upon receiving it, the browser can freshen the stale response using its meta data.
The title sums it all up nicely. I'm asking for the conditions that should be met so Spring decides to send back a Set-Cookie:XSRF-TOKEN=... response header.
I can see that lots of my requests are getting back responses with such header while it is not needed. For instance, when I send a GET request it gets a response with that header set even though I had set the X-XSRF-TOKEN for the request. But for the POST request having the mentioned request header will stop Spring from sending back the set-cookie header. So I wonder what are the conditions that should be met so Spring decides to send back one.
I spent some time tracing Spring Security's source code and I managed to find out the answer myself.
First of all, I didn't know how CSRF works and tracing the code helped me understand it completely. And I think this is something worth knowing. Here's the scenario of requests and responses sent and received from CSRF point of view:
The first request is sent to the server. Since it's the first one, it has no cookie or header set.
Regardless of the request's method, the server (in here Spring Security) looks into the incoming request. If there's no cookie sent to the server under the name XSRF-TOKEN, it will generate a SET COOKIE header on the response's way back.
The client receives the cookie and for the second request, it will add a header to the request under the name X-XSRF-TOKEN set to the same value as the cookie received. Of course, the cookie will be sent to the server with the second request automatically.
When the server receives the second request, this time it has a XSRF-TOKEN cookie, so it will look for a X-XSRF-TOKEN header and the request is considered valid only if these two strings match.
And as for the answer to my question, as I mentioned in step two, the cookie is generated if there's no cookie sent (with XSRF-TOKEN name) to the server. And it does not rely on any other factor - what so ever!
I am facing issue where i am sending one GET request using Jmeter. Response headers shows every time it miss Varnish cache on Server and response is returned from Application Sever. Please find below header
X-Cache: MISS
X-Cache-Hits: 0
If i send exact same request using Postman, first time it miss Varnish cache but if i send same request again, it hits Varnish cache and cache hits counts increased.
X-Cache → HIT
X-Cache-Hits → 1
I have tried Jmeter versions 2.6,2.9,2.11 and 2.13, but observed same behavior. Even when request is sent from Fiddler, i can see from header response is returned from Varnish Cache itself.
It just simple get request. I have compared JMeter and Postman request, both requests are exact same. Please let me know how i can resolve this issue.
Based on when you wrote above, I can guess that:
All 1st requests are processed in the same way, doesn't matter how they were send.
As a part of response to your first request, server returns you a command to set up new header, in the same way as it process cookies (SET-COOKIE logic). So, server expects that your next request will contain this required X-Cache header.
But Jmeter is not a browser and doesn't correlate next request with previously received data (by default at least). So, all is OK if you replay this scenario with browser (and its extensions). And your Jmeter sends the same request every time.
If you compare 1st and 2nd request sent by your browser, you'll find that your 2nd request contains required hearer.
So, if I'm right, to resolve the issue:
Identify the way how your server tells the client to add new header to next request (Javascript?)
Implement this logic in your Jmeter scenario.
Or just add X-Cache header to your request.
My expectation is that Postman (whatever it is) respects ETag header while JMeter doesn't.
I believe adding HTTP Cache Manager should resolve your issue.
I have added unique key in header every time request goes top server and it started returning response from Varnish cache. Unique is random number.
i also checked Postman also send one unique parameter in each and every request. Though I am still not sure why unique is making difference here.
In Is HTTP 303 acceptable for other HTTP methods? we established that HTTP 303 can be used for other HTTP methods.
The Post/Redirect/Get pattern requires the server to carry out an operation before returning HTTP 303. Is the same true for HTTP PUT and DELETE for this and other types of redirects? Is the server required to carry out the operation before redirection? Or can it assume that the client will repeat the request on the canonical URL as necessary?
This becomes even more interesting when you consider the fact that redirection is often used for load-balancing.
Quoting RESTful Web Services page 378:
303 ("See Other")
The request has been processed, but instead of the server sending a response document,
it’s sending the client the URI of a response document. This may be the URI to a static
status message, or the URI to some more interesting resource.
A few pages later...
307 (“Temporary Redirect”)
The request has not been processed, because the requested resource is not home: it’s
located at some other URI. The client should resubmit the request to another URI.
For GET requests, where the only thing being requested is that the server send a representation, this status code is identical to 303 (“See Other”). A typical case where 307 is a good response to a GET is when the server wants to send a client to a mirror site. But for POST, PUT, and DELETE requests, where the server is expected to take some
action in response to the request, this status code is significantly different from 303.
A 303 in response to a POST, PUT, or DELETE means that the operation has succeeded
but that the response entity-body is not being sent along with this request. If the client
wants the response entity-body, it needs to make a GET request to another URI.
A 307 in response to a POST, PUT, or DELETE means that the server has not even tried
to perform the operation. The client needs to resubmit the entire request to the URI in
the Location header.
An analogy may help. You go to a pharmacy with a prescription to be filled. A 303 is
the pharmacist saying “We’ve filled your prescription. Go to the next window to pick
up your medicine.” A 307 is the pharmacist saying “We can’t fill that prescription. Go
to the pharmacy next door.”