nginx proxy_pass 404 error, don't understand why
NginxNginx 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
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;
}
proxy_pass
configuration
Problem with Nginx 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