EmberJs served on nginx - Set Cache-Control header in request - nginx

My application is build using EmberJs and is served on Nginx. I am able to set Cache-Control header in response using add_header in nginx.conf
location ~* \.(css|eot|gif|jpe?g|js|png|svg|ttf|woff2?)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
But this alone doesn't work as request header is set to no-cache. So, browser always goes to backend and doesn't use its cache ever.
Response Headers
cache-control: max-age=315360000
cache-control: public, must-revalidate, proxy-revalidate
expires: Thu, 31 Dec 2037 23:55:55 GMT
pragma: public
Request Headers
Cache-Control: no-cache
Pragma: no-cache
I understand that Cahce-Control in request is causing the problem. But I am not able to find how to set this header with some other value. Does ember build or nginx conf support this?
This is the index.html generated by ember which has links for vendor js and css which are supposed to be reused using cache by browser.

Related

default cache-control headers in nextjs SSR

I have nextjs app. If I add getServerSideProps export to the page (this means that page will be server side rendered, read more) nextjs adds cache-control header:
cache-control: private, no-cache, no-store, max-age=0, must-revalidate
But according to this documentation these are conflicting headers and in theory it should be the same as no-store header. Citing the acticle:
# conflicted
Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
# equivalent to
Cache-Control: no-store
Is there any reason these multiple headers are used instead of simply using no-store?

Nginx missing content-type for woff2

The problem, nginx missing content type for woff2
curl -s -I -X GET https://.../Montserrat-Medium.woff2
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 10 Oct 2018 10:30:54 GMT
Content-Length: 118676
Connection: keep-alive
Keep-Alive: timeout=60
Last-Modified: Wed, 10 Oct 2018 10:27:24 GMT
ETag: "1cf94-577dd4cdf1e25"
Accept-Ranges: bytes
What I've try:
added application/woff2 woff2; to /etc/nginx/mime.types (also application/x-font-woff2, etc)
add to server section this part and it works
location ~* ^.+.woff2$ {
return 403;
}
change part above to this and still have no success
location ~* ^.+\.woff2$ {
proxy_pass https://82.202.226.111:8443;
add_header Content-type application/woff2;
root /var/web/public_shtml;
access_log off;
expires 7d;
try_files $uri #fallback;
}
Also I've view nginx -T configuration to be sure where is no other conditions for woff2.
(3) is almost right. Add also the following to remove the upstream's Content-Type:
proxy_hide_header Content-Type;
Changes to mime.types file are not necessary in this case.
But Richard Smith is right, it's the upstream who returns the wrong content type.

POST response caching does not work in nginx

My task is to implement microcaching strategy using nginx, that is, cache responses of some POST endpoints for a few seconds.
In http section of the nginx.conf I have the following:
proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;
Then I have location in server:
location /my-url/ {
root dir;
client_max_body_size 50k;
proxy_cache cache;
proxy_cache_valid 10s;
proxy_cache_methods POST;
proxy_cache_key "$request_uri|$request_body";
proxy_ignore_headers Vary;
add_header X-Cached $upstream_cache_status;
proxy_pass http://my-upstream;
}
The application located at my-upstream outputs Cache-Control: max-age=10 which, if I understand correctly, should make the responses cacheable.
But when I make repetitive requests using curl in short time (less than 10 seconds)
curl -v --data "a=b&c=d" https://my-host/my-url/1573
all of them reach the backend (according to backend logs). Also, X-Cached is always MISS.
Request and response follow:
> POST /my-url/1573 HTTP/1.1
> Host: my-host
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 113
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 113 out of 113 bytes
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 08 May 2018 07:16:10 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Keep-Alive: timeout=60
< Vary: Accept-Encoding
< X-XSS-Protection: 1
< X-Content-Type-Options: nosniff
< Strict-Transport-Security: max-age=31536000
< Cache-Control: max-age=10
< Content-Language: en-US
< X-Cached: MISS
So the caching does not work.
What am I doing wrong here?
Is there any logging facility in nginx that would allow to see why it chooses not to cache a response?
It turned out that the following directive (which was defined globally) prevented caching from working:
proxy_buffering off;
When I override it under location config with proxy_buffering on;, caching starts working.
So, to make caching work with POST requests, we have to do the following:
Output Cache-Control: public, max-age=10 header on the server
Add proxy_cache_path config and location config in nginx (examples are given in the question text)
Make sure that proxy_buffering is on for the location on which we want to have caching enabled.
To elaborate on #Roman Puchkovskiy's answer above - my origin server was returning the following headers:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
I configured my server to return this instead:
Cache-Control: max-age=3600, public
And now Nginx behaves as expected ✅
I first tried adding this directive to my nginx.conf:
...
location /blah {
...
proxy_ignore_headers Cache-Control;
}
But it looks like that directive doesn't work the way I thought it would.
Note that I wasn't required to add proxy_buffering on to my nginx.conf so it seems I wasn't affected by that issue.

no-cache, no-store, max-age on Cache control header

I am trying to understand the difference between these two cache headers.
In the first header, I have max-age twice - one with value 0 and another with value 600
Cache-Control →no-cache, no-store, max-age=0, must-revalidate, max-age=600
Cache-Control →max-age=600
Can some help me with technically if both are same?

nginx ETag invalidation

I'm caching static resources using the following code in my nginx.conf:
http {
...
gzip on;
gzip_types *;
gzip_vary on;
...
server {
...
location /static {
alias /opt/static_root;
expires max;
}
}
}
This is sufficient to set the following http headers:
$ curl -I example.com/static/css/bootstrap.min.css
Content-Length: 97874
Last-Modified: Mon, 21 Nov 2016 18:30:33 GMT
ETag: "58333d49-17e52"
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
However, even though the Last-Modified date is later than the cached version the browser has, I'm still seeing the old version of the file (tested on Firefox 50.0 and Chrome 54.0.2840.98).
How can I invalidate the ETag so that whenever I deploy diffs to my static files, the browser understands to reload them?
I have tried nginx -s reload, to no avail.
ETags are used when a client makes a Conditional Request to revalidate an expired resource. But in your case the resource won't expire until 2037! The browser will continue to serve the resource from its cache until then without ever checking with the server. That's what you told it to with your Expires header.
Typically if you're going to do far-future expires like that you have to version the resource by changing the name. Or you can change the Expires to something shorter, in which case the ETags will be used when the client tries to revalidate.

Resources