When configuring Nginx proxy_pass, the trailing slash behavior in location blocks often causes confusion. The difference between location /product
and location /product/
is subtle but significant for proper routing.
Consider these two configurations:
# Configuration A (without trailing slash)
location /product {
proxy_pass http://10.0.0.25:8080;
}
# Configuration B (with trailing slash)
location /product/ {
proxy_pass http://10.0.0.25:8080;
}
Configuration A will match:
/product
(exact match)/product/
(redirects to /product)/product123
(prefix match)
Configuration B will match:
/product/
(exact match)/product/subpath
(prefix match)- Will not match
/product
without trailing slash
To properly handle both forms, use this optimized configuration:
location /product {
# Handle case without trailing slash
proxy_pass http://10.0.0.25:8080;
# Optional: Add redirect for consistency
if ($request_uri ~ ^/product[^/]$) {
return 301 $uri/;
}
}
location /product/ {
proxy_pass http://10.0.0.25:8080/; # Note the trailing slash here
}
For more complex scenarios where you need to preserve the URI path:
location ~ ^/product(/.*)?$ {
proxy_pass http://10.0.0.25:8080$1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
- Forgetting the trailing slash in proxy_pass when using trailing slash in location
- Not considering HTTP to HTTPS redirect chains
- Overlooking the difference between prefix matches (=, ~, ^~)
The regex solution (~) is slightly less efficient than prefix matching. For high-traffic sites, consider:
location = /product {
return 301 /product/;
}
location /product/ {
proxy_pass http://backend/;
}
When configuring Nginx proxy rules, the presence or absence of a trailing slash in your location block can significantly impact request routing. Consider these two common but subtly different configurations:
location /product {
proxy_pass http://10.0.0.25:8080;
}
location /product/ {
proxy_pass http://10.0.0.25:8080;
}
The first configuration (/product
) will only match requests to /product
exactly. Meanwhile, the second (/product/
) requires a trailing slash and will match any URI starting with /product/
.
To handle both cases elegantly, you have several options:
Option 1: Exact Match + Prefix Match
location = /product {
return 301 /product/;
}
location /product/ {
proxy_pass http://10.0.0.25:8080/;
}
Option 2: Rewrite Approach
location /product {
rewrite ^/product$ /product/ permanent;
proxy_pass http://10.0.0.25:8080/;
}
Notice the trailing slash in proxy_pass http://10.0.0.25:8080/
. This is crucial for proper URI reconstruction. Without it, Nginx would pass the full original URI to the backend server.
server {
listen 80;
server_name example.com;
# Handle both /api and /api/
location = /api {
return 301 /api/;
}
location /api/ {
proxy_set_header Host $host;
proxy_pass http://backend:3000/;
proxy_redirect off;
}
}
Using exact matches (location =
) first improves performance as Nginx checks these before prefix locations. The 301 redirect has minimal overhead while providing clean URLs.