KevinDockx / HttpCacheHeaders

ASP.NET Core middleware that adds HttpCache headers to responses (Cache-Control, Expires, ETag, Last-Modified), and implements cache expiration & validation models
MIT License
271 stars 57 forks source link

Response is not getting expired and still shows 304 #95

Closed patelbinal closed 3 years ago

patelbinal commented 3 years ago

Hi Team,

I want to implement HTTP caching for my less frequent updating resources with the use of this package. I do have only GET endpoints in my resources let say "years", No PUT endpoint is there. This "years" resource is getting updated a once between 2-3 months period, by few backed activities (Not from the API).

So, I am thinking to use only expiration models. So, after some time the cached response gets expired and it gives me a new response from the server. It is fine if, for some amount of time, I get the stale response until it gets expired. So, I have kept the MaxAge to 120 seconds only, so after 120 seconds response gets expired automatically and the subsequent request is served as a fresh request from the server itself.

Just to inform, my cache location is public (Shared cache) which is shared across multiple clients.

Code snippet for startup file. I am configuring this in the API gateway level, not each service level.

services.AddHttpCacheHeaders(options =>
            {
                options.MaxAge= 60;
                options.CacheLocation = CacheLocation.Public;
            });

And injecting this middleware by
app.UseHttpCacheHeaders();

  1. the First request without If-None-Match is served as fresh request and sends 200 ok response with body and also sends cache-control response headers as below:

Request headers :

1. User-Agent: PostmanRuntime/7.26.10
2. Postman-Token: efde2ce8-ec33-4b06-888e-f5a258ed25f1
3. Host: localhost:5050

Response headers:

1. Date: Fri, 05 Mar 2021 11:16:53 GMT 
2. Content-Type: application/json; charset=utf-8 
3. Server: Kestrel 
4. Content-Length: 1642 
5. Cache-Control: public,max-age=60,s-maxage=60 
6. Expires: Fri, 05 Mar 2021 11:17:54 GMT 
7. Last-Modified: Fri, 05 Mar 2021 11:16:54 GMT 
8. ETag: "C632147C43F297CBF601FDA4AE212893" 
9. Vary: Accept, Accept-Language, Accept-Encoding
  1. Now, I send the second time request before "Fri, 05 Mar 2021 11:17:54 GMT" expires but sending the If-None-Match with the Etag values from the previous response, and I receive 304 Not modified in the response.

Request headers:

1. If-None-Match: "C632147C43F297CBF601FDA4AE212893"
2. User-Agent: PostmanRuntime/7.26.10
3. Postman-Token: 728731de-edd3-46b6-afa9-a0a0f378297d
4. Host: localhost:5050

Response Headers:

1. Date: Fri, 05 Mar 2021 11:20:55 GMT
2. Server: Kestrel
3. Last-Modified: Fri, 05 Mar 2021 11:16:54 GMT
4. ETag: "C632147C43F297CBF601FDA4AE212893"
5. 
  1. Now, suppose "Fri, 05 Mar 2021 11:17:54 GMT" is elapsed, now when I make the same request again with If-None-Match header, it still shows 304 Not modified. Ideally as per the document, if the response is cleared from the cache, then it should hit the server and get the response again with 200 status code as a fresh request. So, I am wondering why the response is not getting expired even after the time elapsed in the "Expires" response header in the first request.

Please help here and let me know which point I am missing on my end.

Do I need to add the validation model options as well with "MustRevalidate" as true which re validates and fires the new requests to the Server?

toddb commented 3 years ago

@patelbinal I had the same issue and this library prior to 5.0.0-beta was implemented with that behaviour.

However, read #82 where it was changed based on the Mozilla documentation. Bottom line is that etag and date modified headers are evaluated independently.

The implementation change is here: https://github.com/KevinDockx/HttpCacheHeaders/blob/master/src/Marvin.Cache.Headers/HttpCacheHeadersMiddleware.cs#L249

Currently, I have reverted to using no-store which as it turns out is really the life cycle of my affected resources.