NGINX cache only images, css, fonts in a specific directory - nginx

location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico)$ {
expires 15d;
add_header Cache-Control "public, no-transform";
}
I have the code above which is supposed to cache these files for 15 days. how do I fix it so that only the files coming from /js, /css, /img will get cached instead of all?

Change the location rule to:
location ~ ^/(js|css|img)/*\.(js|css|png|jpg|jpeg|gif|svg|ico)$ {
expires 15d;
add_header Cache-Control "public, no-transform";
}
That should work

Related

URL from Origin has been blocked by CORS policy when Access-Control-Allow-Origin is set

I have a site that is requesting static files from a CDN. Many of the files are able to be used on the site, but some are being blocked by a CORS policy.
It's blocking html, json, woff, and woff2 files, but letting all other files by, including js, css, jpg and others.
It's a Magento 2 site using nginx. Here is the nginx.conf file where I have added the Access-Control-Allow-Origin:
location /static/ {
# Uncomment the following line in production mode
# expires max;
# Remove signature of the static files that is used to overcome the browser cache
location ~ ^/static/version\d*/ {
rewrite ^/static/version\d*/(.*)$ /static/$1 last;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|svgz|webp|avif|avifs|js|css|eot|ttf|otf|woff|woff2|html|json|webmanifest)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
include /etc/nginx/magento2-cors.conf;
expires +1y;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}
location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
include /etc/nginx/magento2-cors.conf;
expires off;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
add_header X-Frame-Options "SAMEORIGIN";
include /etc/nginx/magento2-cors.conf;
}
And here is magento2-cors.conf:
add_header 'Access-Control-Allow-Origin' '*' 'always';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' 'always';
add_header 'Access-Control-Allow-Headers' 'x-requested-with' 'always';
add_header 'Access-Control-Max-Age' 86400 'always';
add_header 'Content-Length' 0 'always';
return 204;
}
What I don't get is why will CORS block some of the files and not others. All files are coming in through the same CDN. They are all coming from the static directory, which is what the above nginx.conf is referencing. js and css are apart of the same block as html and woff, but they aren't being blocked while html and woff are.
I've flushed browser cache and magento cache. I've restarted nginx multiple times, nothing seems to work.
Instead of using the include, see if putting
add_header Access-Control-Allow-Origin *;
without any if statement around it does the trick.
Try it after this line
location ~* \.(ico|jpg|jpeg|png|gif|svg|svgz|webp|avif|avifs|js|css|eot|ttf|otf|woff|woff2|html|json|webmanifest)$ {
You can also try putting the fonts in a subdirectory (ie: fonts) and see if that improves your situation.
If that doesn't work, try putting the * origin header immediately after
location /static/ {
Best of luck!

Nginx: How to set headers for all the files under a specific folder

So Let's say I have my application where files are under
https://myapp.com/v1/assets/images/*.jpg
and
https://myapp.com/v1/assets/js/*.jpg
I would like to add a rule that would set no-cache headers to anything under /assets
I believe what I can for now do is
location ~ .*assets/js/.*$ {
add_header Cache-Control "public, max-age=0, no-store";
}
location ~ .*assets/images/.*$ {
add_header Cache-Control "public, max-age=0, no-store";
}
But that seems not working plus if I have many other folders under assets, I will need to add a separate rule.
Can I group everything in a pattern so that anything under /assets/* would have that header?
Thanks
This can be done via map directive:
map $uri $cache_control {
~/assets/(images|js)/ "no-cache, no-store, must-revalidate";
}
server {
...
add_header Cache-Control $cache_control;
...
}
If your URI won't match the regex, $cache_control variable would have an empty value and nginx won't add that header to its response. However there are other nginx directives that could affect Cache-Control header, i.e. expires. If you have something like expires <value>; in your config, you can use two map blocks:
map $uri $cache_control {
~/assets/(images|js)/ "no-cache, no-store, must-revalidate";
}
map $uri $expire {
~/assets/(images|js)/ off;
default <value>;
}
server {
...
expires $expire;
add_header Cache-Control $cache_control;
...
}
And take a look at this answer to not be surprised with add_header directive behavior.

Disabling Cache-Control in Nginx for certain IPs

Static files on my server served with browser caching via Cache-Control headers:
location ~* \.(css|js|gif|jpe?g|png)$ {
expires 1h;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
Is it possible to disable this header for certain IPs so they would not cache any files?
P.S. I need it for users who log in as administrators to see the last changes.
The expires directive can be controlled by a variable, usually generated by a map directive. See this document for details.
For example:
map $remote_addr $expires {
default 1h;
10.1.2.3 -1;
}
server {
...
location ~* \.(css|js|gif|jpe?g|png)$ {
expires $expires;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
}
It is assumed that the add_header statements can remain, even if expires is set to -1 to disable the caching.

Exclude folders from caching

In Plesk under Additional nginx directives I've added the following cache settings.
location ~* .(jpg|js|css)$ { #shortened
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
}
But in the wp-admin I have rewrites on the url's of these type of files.
How Do I exclude wp-admin/* and wp-includes/* from the block above?
Bit of background, I run a WordPress multisite in a subfolder. so
maildomain.com/wp-admin/stylesheet.css is actually located in
maildomain.com/wp/wp-admin/stylesheet.css
You can try to experiment with location parameter before caching directives, e.g.:
location ^~ /wp-admin/ {
}
location ~* .(jpg|js|css)$ { #shortened
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
}
UPD. Yes, checked it on my test lab and got the 403 error. I guess empty section is not enough and some directives should be added explicitly.
Managed to add exclusion like the one below:
location ~* "^/(?!wp-admin/|wp-includes/).*\.(jpg|js|css)$" { #shortened
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
}

Set headers for .apk files served by nginx

In my server block I have
location / {
proxy_pass http://echocdn;
include /etc/nginx/mime.types;
add_header Cache-Control "max-age=31536000, private, no-transform, no-cache";
location ~* \.apk$ {
add_header Content-Type application/vnd.android.package-archive;
add_header Content-Disposition "attachment";
}
}
If I remove the inner location block, I can reach the APK file (and all other files).
With the block added, any .apk file returns a 404. How do I add the headers for APK files?
Note: Content types for other file types are handled well by the included mime.types, but even if I add the line for APK files as described How to download ".apk" as ".apk"? (not as ".zip") and https://blog.mypapit.net/2015/08/how-to-set-apk-mime-type-for-nginx-web-server.html it only returns a content-type of text/html for apk files.
maybe it's better not to set a header directly, for me it resulted in a double content-type.
but if you declare it in the location-block types it also works fine.
take a look:
location ~* \.apk$ {
types {
application/vnd.android.package-archive apk;
}
add_header Content-Disposition "attachment";
}
You need to have proxy_pass inside the apk block also. Nginx doesn't work like a programming language so you are not executing anything from the parent block.
Also for setting the content type using default_type directive
location / {
proxy_pass http://echocdn;
include /etc/nginx/mime.types;
#proxy_pass http://127.0.0.1:8082;
add_header Cache-Control "max-age=31536000, private, no-transform, no-cache";
location ~* \.apk$ {
default_type application/vnd.android.package-archive;
add_header Content-Type application/vnd.android.package-archive;
add_header Content-Disposition "attachment";
proxy_pass http://echocdn;
}
}
You can even handle this with a if
location / {
proxy_pass http://echocdn;
include /etc/nginx/mime.types;
#proxy_pass http://127.0.0.1:8082;
add_header Cache-Control "max-age=31536000, private, no-transform, no-cache";
if ($request_uri ~* \.apk$) {
default_type application/vnd.android.package-archive;
add_header Content-Type application/vnd.android.package-archive;
add_header Content-Disposition "attachment";
}
}
Try this:
location ~*.(apk)${
root /tmp/app;
add_header Content-Disposition attachment;
}
/tmp/app is your APK files full path.

Resources