nginx proxy_pass 404 error, don't understand why

Nginx

Nginx Problem Overview


I am trying to pass off all calls to /api to my webservice but I keep getting 404s with the following config. Calls to / return index.html as expected. Does anyone know why?

upstream backend{
    server localhost:8080;
}

 server {

    location /api {
        proxy_pass http://backend;
    }

    location / {
        root /html/dir;
    }
}

More info here

adept@HogWarts:/etc/nginx/sites-available$ curl -i localhost/api/authentication/check/user/email
HTTP/1.1 404 Not Found
Server: nginx/1.2.1
Date: Mon, 22 Apr 2013 22:49:03 GMT
Content-Length: 0
Connection: keep-alive

adept@HogWarts:/etc/nginx/sites-available$ curl -i localhost:8080/authentication/check/user/email
HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 22 Apr 2013 22:49:20 GMT
Transfer-Encoding: chunked

{"user":["false"],"emailAddress":["false"]}

Nginx Solutions


Solution 1 - Nginx

This

location /api {
    proxy_pass http://backend;
}

Needs to be this

location /api/ {
    proxy_pass http://backend/;
}

Solution 2 - Nginx

Just want to remind others that the slash(backend*/*) after your proxy_pass url is very important!

if the config is

location /api/ {
    proxy_pass http://backend;
}

and you visit http://abc.xyz/api/endpoint, you would be directed to http://backend/api/endpoint;

if the config is

location /api/ {
    proxy_pass http://backend/;
}

and you visit http://abc.xyz/api/endpoint, you would be directed to http://backend/endpoint.

That's the difference.

For more, refer to: https://stackoverflow.com/questions/41609509/nginx-reverse-proxy-return-404?rq=1

Solution 3 - Nginx

By some reason proxy_pass in Nginx cuts header "Host" before passing to upstream, and request catches by default server, and even proxy_header_pass doesn't helps, so I've to explicitly set it:

location / {
    proxy_set_header Host $host;
    proxy_pass  http://backend;
}

Solution 4 - Nginx

I forgot to listen on PORT 80, fixed it.

"http" part of nginx config, at: /etc/nginx/nginx.conf, is below:

http {
    server {
        listen 192.111.111.11:80;
        location /path1/ {
            proxy_pass http://127.0.0.1:3000/path1/
        }
    }
}

Now, accessing
http://192.111.111.11/path1/
will get result of accessing
http://127.0.0.1:3000/path1/

NOTE:
Replace the 192.111.111.11 with your IP address in the above.
Run "ifconfig" command, the "inet addr" part will give your IP address

Solution 5 - Nginx

Please check that if you have deleted default.conf file from site-enabled folder. Run the command if you are in debian based ubuntu system

sudo rm /etc/nginx/sites-enabled/default

It worked for me.

Solution 6 - Nginx

Try to troubleshoot step by step to identify which point that possibly cause the issue. Here are some possible mistakes:

The Nginx configuration changed but Nginx did not reload it

This might be occur when you override the nginx.conf file but didn't trigger nginx to reload the config. Might frequently occur to docker user.
To reload the nginx configs, while in the Nginx host, execute command: nginx -s reload
With docker: docker exec <container_name> nginx -s reload
Ref: Controlling NGINX Processes at Runtime

The Nginx default config is overriding yours

This might occurs when nginx.conf also include the default Nginx config and it accidentally override yours, carefully check your nginx.conf if it includes any default config path.
E.g: include /etc/nginx/conf.d/*.conf;, which will also load the nginx default config at the following address
enter image description here
If this is the case, comment out (or remove) this include config statement from your nginx.conf file.

Verify Nginx configuration

Verify the actual config being applied with command nginx -T, this will trigger Nginx to test and print out the configuration, check if the configuration output match your expected result:
Reference: Nginx commandlines
You should see something like the following

root@22a2e5de75ba:/etc/nginx/conf.d# nginx -T
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    server {
        server_name "localhost";
        listen 80;
        location /todo_server/ {
            proxy_pass http://jsonplaceholder.typicode.com;
        }
    }
    # 
    
    include       /etc/nginx/mime.types;
    # default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;
    # include /etc/nginx/conf.d/*.conf;
}
Problem with Nginx proxy_pass configuration

Similar to the previous answer in this thread
This will result in unexpected proxy mapping if you specify the trailing slash / at the end of the URI.
First, see the completed: Nginx proxy_pass document
I'll use the API http://jsonplaceholder.typicode.com/todos/ from jsonplaceholder for demo (it actually serves response for you to test)

With trailing slash
The trailing slash at the end indicate that this proxy_pass directive is specified with a URI. In this case, when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive.

Example: with the following config, which is understood as specified with a URI, will resulted in this mapping

location /path1/ {
    proxy_pass http://jsonplaceholder.typicode.com/todos/;  
    # Requesting http://localhost:8080/path1/ will proxy to => http://jsonplaceholder.typicode.com/todos/
    # Requesting http://localhost:8080/path1/1/ will proxy to => http://jsonplaceholder.typicode.com/todos/1
}

location /path2/ {
    proxy_pass http://jsonplaceholder.typicode.com/;
    # Requesting http://localhost:8080/path2/todos/ will proxy to => http://jsonplaceholder.typicode.com/todos/
}

Without trailing slash
Without the trailing slash /, it's understood as no URI scheme, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI.

location /todos/ {
    proxy_pass http://jsonplaceholder.typicode.com; 
    # Requesting : http://localhost:8080/todos/ will proxy to ==> http://jsonplaceholder.typicode.com/todos/
    # Requesting : http://localhost:8080/todos/1 will proxy to ==> http://jsonplaceholder.typicode.com/todos/1
}

Please also see the completed answer from @dayo and also answer by Richard Smith

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRogeView Question on Stackoverflow
Solution 1 - NginxRogeView Answer on Stackoverflow
Solution 2 - Nginxd0zingcatView Answer on Stackoverflow
Solution 3 - NginxOleg NeumyvakinView Answer on Stackoverflow
Solution 4 - NginxManohar Reddy PoreddyView Answer on Stackoverflow
Solution 5 - NginxSihat AfnanView Answer on Stackoverflow
Solution 6 - NginxThangLeQuocView Answer on Stackoverflow