How can I serve json index properly over nginx? - json

I have the following nginx.conf:
events {}
http {
server {
index index.json;
location /api/some-folder {
alias /some-folder;
default_type application/json;
add_header Content-Type application/json;
}
}
}
With that in place, when the nginx docker image is served on port 8080 and has my json files packed in folder /some-folder, I can browse
http://localhost:8080/api/some-folder/
and I get the content of /some-folder/index.json back. Furthermore, when I browse
http://localhost:8080/api/some-folder/subfolder_1/subfolder_2/some-json.json
then I get the content of /some-folder/subfolder_1/subfolder_2/some-json.json. All fine.
My issue is that I can't seem to find a way to get the /some-folder/index.json content when I browse
http://localhost:8080/api/some-folder
with no trailing slash. When I browse that, I get redirected to
http://localhost/api/some-folder/
which doesn't exist, because nothing is served on port 80. I think I am missing something on how nginx works, and I'd appreciate some help to make it work.
If I simplify my location to just /, then the following configuration works perfectly with and without trailing slash:
events {}
http {
server {
index index.json;
location / {
root /some-folder;
default_type application/json;
add_header Content-Type application/json;
}
}
}
I would like the same behavior as that, but with a location /api/some-folder.
EDIT
Please find here a github repository where the issue is reproduced.

Related

nginx returning index.html for js with 304 response

I have an nginx server that is showing a 200 response in my browser for requests like
https://server.com/app/static/js/2.8cc049f3.chunk.js
and showing a 304 on the server logs
"GET /static/js/2.8cc049f3.chunk.js HTTP/1.1" 304 0 "https://server.com/app"
There is another nginx in front of the nginx running on server.com that is removing the app from the path. Based on the nginx logs on server.com this is working correctly. The static folder is in my root /usr/share/nginx/html/.
The content my browser receives for the js file is the index.html. However when I login to the server and run
curl http://localhost/static/js/2.8cc049f3.chunk.js
I get the correct js content in response and in the logs the server prints 200
"GET /static/js/2.8cc049f3.chunk.js HTTP/1.1" 200 1570391 "-" "curl/7.80.0" "-"
Here is my nginx.conf
server {
listen 80;
root /usr/share/nginx/html/;
index index.html;
add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
try_files $uri $uri/ /index.html;
}
location ~ ^/(static)/ {
gzip_static on;
gzip_types
text/plain
text/xml
text/css
text/comma-separated-values
text/javascript application/x-javascript
application/atom+xml;
expires max;
}
}
I've read that a 304 means the file hasn't changed and tells your browser to use its local cache, so I cleared my browser cache. I also restarted nginx, thinking that the first request would give a 200 response on the server but it was still a 304.
Based on the local curl request being successful I don't think there is anything wrong with my nginx.conf. I don't know if nginx somehow has the index.html cached as the content of my js, or if I didn't clear my browser cache correctly.
I'm also confused why the response code is 304 on the server but 200 in my browser.
The HTTP 304 says "Not-Modified". This is because you are using another NGINX Proxy server in front of the NGINX Server we are talking about.
The 1st NGINX is requesting a resource on the 2nd NGINX and this one answers "Hey that file was not modified since the last time you have asked".
In this case it would be very helpful to check the configuration of the 1st NGINX Proxy instance or your turn of the caching in the first one and proxy_cache off; and check the result.

HTML files are downloaded instead of rendered in browser using NGINX

My contact.html file is being downloaded rather than rendered in the browser when running my site on NGINX.home.html is working properly. This is how my default (in folder sites-available) file looks like:
server {
listen 90;
listen [::]:90;
server_name example.com;
root /home/myname/www;
location / {
try_files $uri /home.html;
add_header Access-Control-Allow-Origin *;
}
location = /contact {
default_type text/html;
alias /home/myname/www/contact.html;
}
}
When I add /contact to my url on my browser, contact.html gets downloaded as unknown file format. After having done an extensive search, these are the things I've tried:
Clear the browser cache (it also happens in Edge, so clearly this isn't the issue)
In nginx.conf I commented out the default_type application/octet-stream and un-commented default_type text/html
I have checked the in mime.types file the type text/html exists.
using try_files $uri /contact.html
Any help will be appreciated!
The issue was that default_type text/html property in nginx.conf lives in http {...} block. Since my server is listening to port 90 this configuration does not apply. once I changed the port to 80 the issue was resolved.

How to prevent chrome load index.html from disk cache after 301 redirect

We have a problem with chrome cache whenever we release a new version of our site, we searched for days and added/removed any header, meta-tags, nginx config, etc which may cause this problem, or is said to fix it, but nothing changed yet. the index.html is still getting cached and we have to press F5 to see the new changes on random computers,
The site is implemented as an SPA, using angularjs framework and is hosted using ngnix which is behind a traefik proxy, using traefik rules, we force redirect HTTP requests to HTTPS by 301 response.
today I found the failing scenario! if a user enters the https protocol in the address bar (e.g. https://example.com), everything is working correctly but if the user comes back and tries to visit http://example.com, chrome will redirect the user to https via 301 redirect cache, then loads a cached version of index.html which is not what we want, it is ok that 301 redirect is cached, but we want chrome to get the index.html from server not loading it from disk cache!
Note: as long as a user is using HTTPS, the index is loaded from the server or gets 304 response, we want this to happen when the user enters just the domain itself, not with https.
this is meta tags which are added to index.html:
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="pragma" content="no-cache" />
and here is part of our nginx config:
...
http {
...
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=prerender_cache:100m max_size=10g inactive=1d;
proxy_cache_key "$request_method$host$request_uri$is_args$args";
...
server {
access_log /dev/stdout combined1;
listen 80 default_server;
server_name example.com;
root /app;
index index.html;
...
location ~ ^/(assets|static|styles) {
expires 31d;
add_header Cache-Control public;
}
location #asset_pass {
root app/;
try_files $uri =404;
}
location / {
expires -1;
add_header Pragma "no-cache";
add_header Cache-Control "no-store, no-cache, must-revalicate, post-check=0 pre-check=0";
try_files $uri #prerender;
autoindex on;
}
location ~ \.html$ {
expires -1;
add_header Pragma "no-cache";
add_header Cache-Control "no-store, no-cache, must-revalicate, post-check=0 pre-check=0";
}
}
}
Now the question is: is there any way to fix this or this is the default behavior of google chrome?
Thank you all for taking the time to read this question and sorry if it was too long.
You can try to touch your index.html file, then response header last-modified will changed to latest date time, so browser will consider this resource to be 'outdated', latest 301 rule will be applied;

NGINX, proxy_pass and SPA routing in HTML5 mode

I have NGINX set up as a reverse proxy for a virtual network of docker containers running itself as a container. One of these containers serves an Angular 4 based SPA with client-side routing in HTML5 mode.
The application is mapped to location / on NGINX, so that http://server/ brings you to the SPA home screen.
server {
listen 80;
...
location / {
proxy_pass http://spa-server/;
}
location /other/ {
proxy_pass http://other/;
}
...
}
The Angular router changes the URL to http://server/home or other routes when navigating within the SPA.
However, when I try to access these URLs directly, a 404 is returned. This error originates from the spa-server, because it obviously does not have any content for these routes.
The examples I found for configuring NGINX to support this scenario always assume that the SPA's static content is served directly from NGINX and thus try_files is a viable option.
How is it possible to forward any unknown URLs to the SPA so that it can handle them itself?
The solution that works for me is to add the directives proxy_intercept_errors and error_page to the location / in NGINX:
server {
listen 80;
...
location / {
proxy_pass http://spa-server/;
proxy_intercept_errors on;
error_page 404 = /index.html;
}
location /other/ {
proxy_pass http://other/;
}
...
}
Now, NGINX will return the /index.html i.e. the SPA from the spa-server whenever an unknown URL is requested. Still, the URL is available to Angular and the router will immediately resolve it within the SPA.
Of course, now the SPA is responsible for handling "real" 404s. Fortunately, this is not a problem and a good practice within the SPA anyway.
UPDATE: Thanks to #dan

Nginx server does not load css files from skeleton framework

Hey there,
I'm new when dealing with NIGNX servers and Linux. My HTML file is displayed but my server does not load the CSS files.
The only thing I found was this line
include /etc/nginx/mime.types;
which I include in the http block.
After that I reload my config with sudo nginx -s reload. To be sure I also executed sudo nginx -s stop and sudo nginx.
This is my whole config:
http {
include /etc/nginx/mime.types;
server {
location / {
root /data/www;
}
location ~ \.(gif|jpg|png)$ {
root /data/www/images;
}
}
}
events {}
My skeleton files are located in /data/www. In this directory there is another CSS folder.
Thank you in advance.
First of all, you're going to need to tell NGINX to have your static files to obtain a TTL (time to live) via expire headers. Locate this in your NGINX configuration file, if it isn't there. Create a new directive with location
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1s;
}
After this go ahead and purge your files from the server and force it to serve new files.
Set sendfile off in nginx.conf
Set expires 1s in mysite.conf
Explicitly set Cache-Control header: add_header Cache-Control no-cache;
Of course, before doing anything above. If it doesn't require drastic measure, try manually deleting everything in the cache folder: /var/cache/nginx
If that doesn't help then proceed with everything listed here!
After you've successfully purged your server from serving static files. Add this to your NGINX server block to achieve optimization.
gzip on;
gzip_comp_level 2;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/x-javascript text/xml text/css application/xml;
It's possible to set expire headers for files that don't change and are served regularly.
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}