Volley sends If-Modified-Since when the document does not have Last-Modified - android-volley

I'm using Android Volley Networking library in a project.
When I add "if-None-Match" with etag to the header myself I am not getting 304 because Volley also adds "If-Modified-Since". The cached response did not have "Last-Modified" in the header.
Should Volley send "If-Modified-Since", if the cached request did not have "Last-Modified"?

tl;dr: no, I don't believe Volley should be sending If-Modified-Since as part of its requests, at least not the way it is currently doing it.
Longer answer:
Volley is setting the If-Modified-Since header using the Date header from the previous response here and here.
Looks like there's a patch here to fix volley so that it behaves more appropriately (i.e., uses the Last-Modified response header).
Here's two subsequent requests that both yield 200 responses from Volley/Android:
Request 1
If-None-Match: "cd090c6cb990a25585f1748d85d764bd"
If-Modified-Since: Tue, 16 Dec 2014 14:21:13 GMT+00:00
Response 1
ETag: "cd090c6cb990a25585f1748d85d764bd"
Date: Tue, 16 Dec 2014 14:21:29 GMT
Request 2
If-None-Match: "cd090c6cb990a25585f1748d85d764bd"
If-Modified-Since: Tue, 16 Dec 2014 14:21:29 GMT+00:00
Response 2
ETag: "cd090c6cb990a25585f1748d85d764bd"
Date: Tue, 16 Dec 2014 14:23:31 GMT
The responses don't include the Last-Modified header so http clients don't have an appropriate value for If-Modified-Since... yet Volley sends If-Modified-Since with the Date value from the previous response.

Related

Cloudflare caching resources for which cookie is set

I'm setting some cookies and appropriate cache-headers (to not cache) while responding a requested .gif file. According to Cloudflare documentation:
If the Cache-Control header is set to "private", "no-store", "no-cache", or "max-age=0", or if there is a cookie in the response, then Cloudflare will not cache the resource.
I know that there's a default caching of .gif files but I can see 'CF-Cache-Status:MISS' in response-header. So, the issue is not caching but that the cookie is not being forwarded to client from my backend server.
Response Header sent by my backend server:
Cache-Control:no-cache, no-store, must-revalidate
Content-Type:image/gif
Content-Length:12345
Date:Wed, 12 Jul 2017 13:50:29 GMT
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Pragma:no-cache
Set-Cookie:user=randomuser; Max-Age=7776000; Expires=Tue, 10-Oct-2017 13:38:45 GMT
Response Header sent by Cloudflare:
Cache-Control:no-cache, no-store, must-revalidate
CF-Cache-Status:MISS
CF-RAY:xxxxxxxxxxxxx-XXX
Connection:keep-alive
Content-Type:image/gif
Content-Length:12345
Date:Wed, 12 Jul 2017 13:50:29 GMT
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Pragma:no-cache
Server:cloudflare-nginx
Vary:Accept-Encoding
As can be seen the 'Set-Cookie' header is not forwarded to my clients by Cloudflare.
Although this issue got resolved when I created a page rule and set Bypass Cache for the resource-url.
Can anyone guide me what am I missing or additional headers to send from my backend server so that 'Set-Cookie' is also forwarded through Cloudflare?

Cloudfront - why is this not being "browser cached"?

Here's the curl -I response to my Javascript file:
HTTP/1.1 200 OK
Content-Type: text/javascript
Content-Length: 72640
Connection: keep-alive
Date: Sat, 18 Feb 2017 16:12:06 GMT
Cache-Control: 86400
Last-Modified: Wed, 15 Feb 2017 15:09:28 GMT
ETag: "a6ee06ff5e49a4290bb2aabe5e0f9029"
Server: AmazonS3
Vary: Accept-Encoding
Age: 1173
X-Cache: Hit from cloudfront
Via: 1.1 3b17302562f1709d8b6c9f7be1.cloudfront.net (CloudFront)
I can see the Cache-Control tag there. Not sure what the Vary and the ETag are doing, but so be it. Does this somehow specify to a user's browser NOT to cache this file? Why are Pingdom or Goog PageSpeed not recognising this as a browser-cacheable file?
Your Cache-Control header is present, but the value is not actually valid. The correct format looks like this:
Cache-Control: max-age=86400
The number, by itself, is meaningless.
ETag: is the entity tag -- an opaque value that uniquely identifies the current content of a given URL. If the content changes, the ETag will also change. A browser with a cached copy may use this value for subsequent requests to ask that the server only return the content if it differs, by sending an If-None-Match: request header, including the last-seen ETag.
Vary: tells the browser that certain changes to the request may generate a different response. Unlike browsers, curl doesn't advertise its ability to support gzipped payload unless you specify the --compressed option. Adding that option when invoking curl triggers the addition of Accept-Encoding: gzip to the request, which may trigger the response to be compressed if you have that option enabled in CloudFront.

When serving a response cached by the server, IIS 7 is stripping the Vary header

I’m using a custom framework for bundling stylesheets and scripts. (I.e., these are dynamically generated responses, not static files.)
The response for the initial request, when the response is being generated for the very first time, includes these headers:
HTTP/1.1 200 OK
Cache-Control: public, no-transform, max-age=31536000
Content-Type: text/css; charset=utf-8
Content-Encoding: gzip
Last-Modified: Mon, 25 Aug 2014 18:15:50 GMT
Vary: Accept-Encoding
Date: Tue, 09 Sep 2014 16:19:36 GMT
Content-Length: 3126
Now that the response above has been generated and cached by the server, subsequent requests for the same stylesheet are responded to with these headers:
HTTP/1.1 200 OK
Cache-Control: public, no-transform, max-age=31536000
Content-Type: text/css; charset=utf-8
Content-Encoding: gzip
Last-Modified: Mon, 25 Aug 2014 18:15:50 GMT
Date: Tue, 09 Sep 2014 16:20:00 GMT
Content-Length: 3126
Ignoring the new Date value, the headers are identical with the obvious exception of the missing Vary header.
One nasty consequence that I’ve seen in the wild is that if the very first response generated for a given asset is not compressed (due to the corresponding client not supporting compression), then the server caches that non-compressed response and serves it for all subsequent requests to all clients.
Any idea how to have the server retain the Vary header for cached responses?
I’m using HttpCacheability.Public for these responses. I can avoid the issue by using HttpCacheability.Private instead, but I’d prefer to allow the server and proxies to cache responses.
Some reading has led me to believe that IIS can’t do “kernel caching” if you vary by encoding. But I’m not sure if that means I can’t cache on the server at all or if it just prevents a special kind of server-side caching.
Update:
I was originally using the following to set the Vary header:
response.AppendHeader("Vary", "Accept-Encoding");
I tried a different method of specifying it:
response.Cache.SetVaryByCustom("Accept-Encoding");
That caused Vary to never be emitted. Not even on the very first response.
As a last resort, I’m also considering using:
response.Cache.SetNoServerCaching();
That causes the Cache-Control header to still specify public (so that proxies can still cache), but prevents the server from caching.
In line with the update I made to the question, I tried yet another way of specifying the Vary header:
response.Cache.VaryByHeaders["Accept-Encoding"] = true;
…And it fixed the problem. Responses now retain the Vary header across requests from multiple clients and are also cached by the server.

Why caching ajax request is not working?

I have a large json data object (over 300K uncompressed, 40K gzipped) which is used on every page of my internal system. I want to fetch it every 15 minutes. In this time user will probably visit tens of pages of my system.
The HTTP Response headers in Firebug look like:
Cache-Control max-age=899, public
Connection Keep-Alive
Content-Encoding gzip
Content-Length 44017
Content-Type text/html; charset=iso-8859-2
Date Tue, 04 Dec 2012 16:21:45 GMT
Expires Tue, 04 Dec 12 17:36:45 +0100
Keep-Alive timeout=15, max=99
Last-Modified Tue, 04 Dec 12 17:21:45 +0100
Pragma no-cache
Server Apache
Set-Cookie user_auth=xxx; expires=Wed, 12-Dec-2012 16:21:45 GMT; path=/; domain=example.com
Vary Accept-Encoding
X-Genaration-Time 0.13282179832458 sec.
X-Genarator vCRM 3.1 (c) Veracomp S.A.
X-Powered-By PHP/5.3.3-7+squeeze14
The cache headers are set to 15 minutes in future, but neither Chrome nor Firefox caches it.
The Firebug says this about cache:
Data Size 44017
Device disk
Expires Thu Jan 01 1970 01:00:00 GMT+0100
Fetch Count 5
Last Fetched Tue Dec 04 2012 17:21:45 GMT+0100
Last Modified Tue Dec 04 2012 17:21:45 GMT+0100
It seams the Expires header is ignored, but why?
This sould not mattery, but I better write, that the content type is text/html, so the server can gzip it, but in reality the content is JSON.
I am using Prototype.js to request this. I set the request header:
Cache-control: max-age=900
Prototype.js does not add any cache buster parameter to the url.
I am using PHP with Zend_Framework to set serve the response.
What am I doing wrong?
Problem solved.
As #Victor pointed out, I had the "Pragma: no-cache" header set. The header was somehow set by PHP. I worked with our webserver admin and we had managed to unset the header with Apache.
Still it was not enough. Our framework sets cookies with every page refresh and I could not turn it of. Browsers did not want to cache the requests which set cookies. We had to unset the Set-Cookie headers too.
Finally this two unsets allowed us to enable cache:
<LocationMatch "(?i)/url/we/want/to/be/cached/.+">
Header unset Pragma
Header unset Set-Cookie
</LocationMatch>

Sprockets max-age header on heroku

My application.js file name looks like application-b600352536291bc180983d43e6a2407f.js. So it has the md5 cache buster in its name. I have set the max-age option for static assets to 1 hour config.static_cache_control = "public, max-age=3600". But i am observing that the browser is not respecting the max-age header and always revalidates from the server and does a round trip for a 304 Not Modified. How can i save the round trip?
Request Headers
Request URL:https://blah.com/assets/application-b600352536291bc180983d43e6a2407f.js
Request Method:GET
Status Code:304 Not Modified
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
If-Modified-Since:Sun, 12 Feb 2012 07:36:16 GMT
Response Headers
Cache-Control:public, max-age=3600
Connection:keep-alive
Date:Sun, 12 Feb 2012 18:27:48 GMT
Last-Modified:Sun, 12 Feb 2012 07:36:16 GMT
Server:nginx
Vary:Accept-Encoding
Via:1.1 varnish
X-Varnish:499878183
Are you pressing Command + R or Ctrl + R? The browser refresh button intentionally re-checks the freshness of its assets. It assumes you're hitting refresh because something didn't function properly on the page.
If you want to test the headers, visit the page once and then focus the location bar and press Enter to visit it a second time. The assets should come from the cache.

Resources