Nginx Cache: how to expire/vary by request date - caching

I've got content that changes depending on the date it is requested on, i.e.
the same content will be served when the page is requested at 2018-09-10T00:00 and 2018-09-10T23:59, but different content will be served at 2018-09-11T00:00 (based on the server time).
Is there a vary http header I can set on the content that will achieve this (set by the upstream server)?
Or is there another way of doing this in nginx (ideally only on certain paths)?

Client-side caching is controlled by setting cache control headers.
See http://nginx.org/en/docs/http/ngx_http_headers_module.html#expires for a discussion of the options. It is possible to specify the time of day using the # prefix. So your config would look something like this for setting expiry at 3:30 pm server time:
location ~* \.(css|js)$ {
expires #15h30m;
add_header Cache-Control "public";
}
If your content expired every hour, you could so something fancy like do a time calculation in lua and set that to an ngx variable which is used by expire.

You need to add a "Expires" header, which you can do in Nginx or in your application. The header would look like this, just as an example:
Expires: Sun, 09 Oct 2016 23:59:59 GMT
In PHP you could generate this with:
header('Expires: ' . gmdate('D, d M Y H:i:s', strtotime(date("Y-m-d 23:59:59"))) . ' GMT');
In Nginx you just need to add the following to your location or server block which serves the specified content:
expires #00h00m;
That way the content would expire at midnight.

Related

Firefox always caches when Last-Modified header is set [duplicate]

I want to find a minimal set of headers, that work with "all" caches and browsers (also when using HTTPS!)
On my web site, I'll have three kinds of resources:
(1) Forever cacheable (public / equal for all users)
Example: 0A470E87CC58EE133616F402B5DDFE1C.cache.html (auto generated by GWT)
These files are automatically assigned a new name, when they change content (based on the MD5).
They should get cached as much as possible, even when using HTTPS (so I assume, I should set Cache-Control: public, especially for Firefox?)
They shouldn't require the client to make a round-trip to the server to validate, if the content has changed.
(2) Changing occasionally (public / equal for all users)
Examples: index.html, mymodule.nocache.js
These files change their content without changing the URL, when a new version of the site is deployed.
They can be cached, but probably need a round-trip to be revalidated every time.
(3) Individual for each request (private / user specific)
Example: JSON responses
These resources should never be cached unencrypted to disk under no circumstances. (Except maybe I'll have a few specific requests that could be cached.)
I have a general idea on which headers I would probably use for each type, but there's always something I could be missing.
I would probably use these settings:
Cache-Control: max-age=31556926 – Representations may be cached by any cache. The cached representation is to be considered fresh for 1 year:
To mark a response as "never expires," an origin server sends an
Expires date approximately one year from the time the response is
sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one
year in the future.
Cache-Control: no-cache – Representations are allowed to be cached by any cache. But caches must submit the request to the origin server for validation before releasing a cached copy.
Cache-Control: no-store – Caches must not cache the representation under any condition.
See Mark Nottingham’s Caching Tutorial for further information.
Cases one and two are actually the same scenario.
You should set Cache-Control: public and then generate a URL with includes the build number / version of the site so that you have immutable resources that could potentially last forever.
You also want to set the Expires header a year or more in the future so that the client will not need to issue a freshness check.
For case 3, you could all of the following for maximum flexibility:
"Cache-Control", "no-cache, must-revalidate"
"Expires", 0
"Pragma", "no-cache"

How long should we set the HTTP Expires or Cache-control: max-age header?

Let's say if the bundle.js is 750kb, is it true that if you set it to "never expire" or "expire in 10 years", then the browser doesn't need to fetch that file and therefore can make your website and pageload faster?
(By the way, it is said that Cache-control: max-age is HTTP/1.1 and if it and Expires: are both present, Cache-control overrides the Expires header.)
What if you have a weekly or 2-month release cycle, should you set the Expires header to 1 week or 2 months? I was thinking that with a weekly release cycle, some of your JavaScript or CSS files may stay the same, so it may be good to just set it to expire in 6 months or even 10 years? (because one week later it hasn't changed?)
But what if your file changed but the browser doesn't fetch it? Is it true that if you use the ETag mechanism, or if you use bundle.53ae823.js or bundle.2020-03-12-08.js, then you can "force" it to expire by the ETag being different, or the file name being different? What is a good way to set the Expires header length?
You could use all of those techniques at the same time. If you can include a hash in your filenames and the references to them (example of how to do it in webpack), then you can be sure that you can bust the cache whenever you change something.
Then you could set Cache-control: max-age to 31536000 (a year, the max) because you can trust the file with URI to not change (because of the hash, if the file changes ,the URI will too).
And of course you can implement ETAG in order to enable revalidation of the cache. This will still require a request to be sent to your server/CDN, but will save the user having to download the whole file if it hasn't changed.
There is a nice article on this topic, here.

Cookie expiry date is taking session value in magento

I want to set session timeout limit for one of the store views in my magento site,
Done too much R&D by surfing several sites, but doesn't come up with any solution
Here is the explanation:
My cookie settings ib admin panel for default config
System->Configuration->Web->Session Cookie management
Cookie Lifetime 900
Cookie Path /
Cookie Domain (blank)
Use HTTP Only yes
And my store view settings
Cookie Lifetime 120
Cookie Path /
Cookie Domain (blank)
Use HTTP Only yes
adminhtml iub2qjrvtcvv46rutus50gngo6 mydomain.com / Session 35
frontend 573ofasrb0l7ems6kr5nv1mo01 mydomain.com / Session 34
frontend 573ofasrb0l7ems6kr5nv1mo01 .mydomain.com / Wed, 03 Sep 2014 09:23:40 GMT 34
Is there any wrong in my settings and why the cookie expiry date is taking as "session" and the cookie is not expiring in 120 seconds.
I find out the solution. In magento cookies time always set in second, you need to convert your date or time to seconds then you will set your cookies in magento according to you.
// Cookies set for one month in magento:
$expire = strtotime(date("m/d/Y, H:i:s A", time() + 60 * 60 * 24 * 30));
$cookies = Mage::getModel('core/cookie')->set('name', 'value', 'expire');
Output: 09/13/2015, 10:43:39 AM (calculate with current date).

Varnish cache miss with json content type

I'm using the following vcl to help me determine if I'm getting a Varnish cache hit or a miss:
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Varnish-Cache = "HIT";
}
else {
set resp.http.X-Varnish-Cache = "MISS";
}
}
This is working fine, but not for application/json content type.
I'm getting X-Varnish-Cache = "MISS" on every request, but I can't see why this would be happening (and I have a suspicion that it's a false negative).
Here's an example of the response headers for my (apparently) non cached json request:
Accept-Ranges:bytes
Age:0
Cache-Control:public, max-age=10800
Connection:keep-alive
Content-Encoding:gzip
Content-Length:2139
Content-Type:application/json
Date:Thu, 09 Jan 2014 16:08:21 GMT
Etag:"1389283199-1"
Expires:Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified:Thu, 09 Jan 2014 15:59:59 +0000
Server:Apache
Vary:Cookie,Accept-Encoding
Via:1.1 varnish
X-Drupal-Cache:HIT
X-Powered-By:PHP/5.3.23
X-Varnish:544296535
X-Varnish-Cache:MISS
If I look at the response times, it's 8 times quicker on subsequent requests to the same url (so 800ms for the first time, and 100ms the second and then on). This makes me think that Varnish is caching, but my vcl is incorrect.
I should also add that no cookies are being sent with the request, and it's a GET request.
Your VCL is correct (BTW: when varnish response comes from cache X-Varnish header comes with 2 numbers).
The response times improves due to Drupal caching.
Probably JSON is not being cached because of the cookies or your VCL.
You have a working VCl for drupal on https://github.com/NITEMAN/varnish-bites/blob/master/varnish3/drupal-base.vcl
Anyway, to trace the issue your full VCL and a varnishlog trace of the request.

Rack::Cache/Rack::Etag 304

I use Rack:Etag to genereate proper etag values based on the response from the server and for development I use Rack::Cache to verify that that caching I expect to happen really does
But i have a slight predicament:
I send a request and get these headers back
Age →0
Cache-Control →public, max-age=10
Connection →keep-alive
Content-Length →4895
Content-Type →application/json; charset=UTF-8
Date →Wed, 02 Oct 2013 06:55:42 GMT
ETag →"dd65de99f4ce58f9de42992c4e263e80"
Server →thin 1.5.1 codename Straight Razor
X-Content-Digest →0879e41b0d8e9b351f517dd46823095e0e99abd8
X-Rack-Cache →stale, invalid, store
If i after 11 seconds send a new request with If-None-Match=dd65de99f4ce58f9de42992c4e263e80 then i expect to get a 304 but always get 200 with the above headers.
What am I missing ?
Could it be due to max-age directive being set to 10
When the max-age cache-control directive is present in a cached response, the response is stale if its current age is greater than the age value given (in seconds) at the time of a new request for that resource.
Although, did you already know that? As you tried after 11 secs!
I think the solution was to load the rack middleware as follows for coorect chaining
use Rack::Cache
use Rack::ConditionalGet
use Rack::ETag
And also send If-None-Match with "" around hash, which i think seems pretty fragile

Resources