Getting a mimetype error when serving two apps on one domain

Viewed 66

I have two node apps running at two different ports.

To get nginx to appropriately route requests, I have two location blocks,

# /etc/nginx/sites-available/my_site.com
server {
    root /var/www/my_site.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name my_site.com www.my_site.com;

    location / {
            proxy_pass http://localhost:5001;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
    }

    location /app2 {
            proxy_pass http://localhost:5000;
            proxy_http_version 1.1;
            proxy_redirect off;
    }
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my_site.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my_site.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

Now, the app running at port 5001 works fine. Trying to visit my_site.com or making requests to its API services through postman works as expected.

However, the moment I try to visit my second app app2 that is running on port 5000, I am met with a blank white screen and the following in my console:

Refused to execute script from 'https://my_site.com/path/to/static/js/main.61886448.chunk.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

I've verified that these files that the client is trying to access exist and that the http block in nginx.conf includes the following line,

http {
    . . .
    include /etc/nginx/mime.types;
    . . .
}

My frontend app attempts to make requests https://my_site.com/path/to/static with a successful 200 response code, indicating, to me at least, that the path itself is correct.

What am I doing wrong here? If you're wondering, why my app2 location block is as empty as it is, it's because I kept getting 304 redirect status codes, instead of 200.

I'm equally unable to hit my healthcheck endpoint. It would have lived at http://localhost:5000/api/health, if I didn't have that second location block, but because I do, I try to make a request to http://localhost:5000/app2/api/health -- but this fails as well.

1 Answers

The error

Refused to execute script from 'https://my_site.com/path/to/static/js/main.61886448.chunk.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

is from the browser which says that it was expecting a javascript file in the response. Instead, it got something else (a blank text/html response may be). The path 'https://my_site.com/path/to/static/js/main.61886448.chunk.js' doesn't satisfy the /app2 rule and instead goes to the first location block which is sending a 200 status code html response (the error message might be inside the html elements).

The neatest solution would be to add /app2/ prefix in all your resources in the application hosted on port 5000 as pointed out by Richard in the comments.

However, if you only care about static files you can write one more location block matching all static requests ending with .js, .css, .png, .jpg, etc.

location ~* .(png|ico|gif|jpg|jpeg|css|js)$ {
    proxy_pass http://localhost:5000;
}

This will ensure that your static files are served by localhost:5000. Additionally, if the browser side application is making XHR requests to the backend you might need to add additional location blocks proxy_passing them to correct path.

About the last healthcheck endpoint error, it is coming because according to your location directive rule. According to your rule requests coming to https://my_site.com/app2/api/health will be proxied to http://localhost:5000/app2/api/health which will give you a 404 if the path /app2/api/health doesn't exist in your application. In order to proxy https://my_site.com/app2/api/health to http://localhost:5000/api/health, the correct rule should be:

location /app2/ {                        # <--- notice trailing slash here
    proxy_pass http://localhost:5000/;   # <--- notice trailing slash here
    proxy_http_version 1.1;
    proxy_redirect off;
}
Related