I have a simple location block in my nginx config which matches static files for my website. What I want to do, is to check if the file exists using try_files, and if it doesn't, redirect to a URL (in this case specified in the @cdn location block). I also want to set some CORS headers.
Below is the relevant configuration.
location ~* \.(css|js|jpe?g|png|gif|otf|eot|svg|ttf|woff|woff2|xml|json)$ { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; } try_files $uri @cdn; } location @cdn { return 301 https://example.com$request_uri; } The problem is that I get a 404 response if the file does not exist, instead of a 301 redirect. The configuration worked/works fine before adding the CORS headers. If I remove the handling of the headers, everything works as intended, and I get a 301 response back.
Now I have done a bit of reading about why the if directive is bad and should be avoided, but I still don't know why it breaks my configuration. If I understood correctly, it has something to do with either if or add_header being part of a rewrite module or something like that, and I guess that conflicts with try_files. Perhaps I am not accurate here, but either way I am not sure how to fix it.
Why does the presence of if and/or add_header make nginx give me a 404 instead of a 301 when a file could not be found, and how do I fix it? Thanks in advance!