How to Properly Redirect Nginx Subpath to External Host Using Proxy Pass


2 views

When attempting to redirect a subpath to an external server, the common pitfall is improper URI handling. The error "rewritten URI has zero length" typically occurs when the rewrite rule completely strips the URI path.

location /tomcatapi/ {
    rewrite /tomcatapi/(.*) $1 break;
    proxy_pass http://192.168.0.3:8443;
}

The solution is to either remove the rewrite rule entirely or modify it to preserve the path information while still removing the prefix:

# Option 1: Simple proxy_pass with trailing slash
location /tomcatapi/ {
    proxy_pass http://192.168.0.3:8443/;
}

# Option 2: Rewrite alternative
location /tomcatapi/ {
    proxy_pass http://192.168.0.3:8443$request_uri;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

Here's a production-ready configuration with additional best practices:

server {
    listen 80;
    server_name www.myservice.com;

    location /tomcatapi/ {
        proxy_pass http://192.168.0.3:8443/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # Timeout settings
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        send_timeout 60s;
    }
}

After implementing the configuration, verify it works by:

  1. Reloading Nginx: sudo nginx -s reload
  2. Testing with curl: curl -v http://www.myservice.com/tomcatapi/
  3. Checking logs: tail -f /var/log/nginx/error.log

For HTTPS backends or complex routing scenarios:

location ~ ^/tomcatapi(/.*)$ {
    proxy_pass https://192.168.0.3:8443$1;
    proxy_ssl_certificate /path/to/cert.pem;
    proxy_ssl_certificate_key /path/to/key.pem;
    proxy_ssl_verify off; # Only for testing
}

When trying to route a subpath to an external service, many developers encounter issues with URI rewriting and proxy configurations. The specific error the rewritten URI has a zero length typically occurs when the rewrite rule strips the entire path component.

Here's the proper way to configure Nginx to proxy requests from /tomcatapi/ to an external Tomcat server while preserving the request path:


location /tomcatapi/ {
    proxy_pass http://192.168.0.3:8443/tomcatapi/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

The key difference is that we're:

  • Appending the subpath to the proxy_pass destination
  • Removing the problematic rewrite rule
  • Including essential proxy headers

If you need to modify the path structure, this alternative approach might be more suitable:


location /tomcatapi/ {
    proxy_pass http://192.168.0.3:8443/;
    rewrite ^/tomcatapi/(.*)$ /$1 break;
    proxy_set_header Host $host;
    # Other proxy headers...
}

For different scenarios, consider these configurations:


# When backend expects different path prefix
location /frontend-path/ {
    proxy_pass http://backend:port/backend-path/;
}

# When removing path prefix completely
location /remove-this/ {
    proxy_pass http://backend:port/;
    rewrite ^/remove-this/(.*)$ /$1 break;
}

# For WebSocket proxying
location /ws/ {
    proxy_pass http://websocket-backend:port/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
  • Check Nginx error logs: tail -f /var/log/nginx/error.log
  • Verify connectivity: curl -v http://192.168.0.3:8443/tomcatapi/
  • Test configuration: nginx -t
  • Reload Nginx after changes: nginx -s reload