Nginx Dynamic Proxy_pass Subdomain Routing: Fixing URL Redirection Issues for Tomcat Applications


4 views

When implementing dynamic subdomain routing with Nginx reverse proxy to Tomcat applications, many developers encounter unexpected URL redirection behavior. The browser ends up displaying the backend server's URL (e.g., http://localhost:8080/myapp) instead of maintaining the original requested domain (www.myapp.example.com).

Tomcat applications often generate absolute URLs with the backend server's context path, causing the browser to redirect to the internal address. The key issues are:

  • Missing proper Host header forwarding
  • Inadequate proxy_redirect configuration
  • Context path mismatches between frontend and backend

Here's the complete solution that handles both the initial request and subsequent redirects:

http {
    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        server_name ~^(www\.)?(?<sub_domain>.+)\.example\.com$;
        listen 80;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://backend/prefix-$sub_domain$request_uri;
            
            # Handle redirects from Tomcat
            proxy_redirect http://$host/prefix-$sub_domain http://$host;
            
            # Additional recommended settings
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

1. Host Header: The proxy_set_header Host $host ensures Tomcat receives the original domain name.

2. Proxy Redirect: The proxy_redirect directive rewrites Location headers in 3xx responses from Tomcat.

3. Request URI: Using $request_uri preserves the original path including query parameters.

Performance Impact

The regex-based server_name and variable substitution do add minimal overhead, but it's negligible for most use cases. The real performance factors are:

  • Connection keep-alive between Nginx and Tomcat
  • Proper buffer sizing in proxy directives
  • Caching static assets at Nginx level

Filtering Request URI

To remove session IDs or other parameters from the URI, use a rewrite rule before proxy_pass:

location / {
    rewrite ^/(.*)$ /$1? break;
    proxy_pass http://backend/prefix-$sub_domain;
    ...
}

For applications that can't modify their base URL, consider URL rewriting:

location / {
    rewrite ^/(.*)$ /prefix-$sub_domain/$1 break;
    proxy_pass http://backend;
    ...
}

Use these curl commands to test your configuration:

# Check initial response
curl -v http://myapp.example.com

# Follow redirects
curl -v -L http://myapp.example.com

# Check headers
curl -I http://myapp.example.com

Remember to check both Nginx and Tomcat access logs when debugging.


When setting up Nginx as a reverse proxy for wildcard subdomains, many developers encounter issues where the proxy_pass directive doesn't properly resolve dynamic backend paths. The common symptom is that requests get redirected to the literal backend URL (like http://localhost:8080/myapp) instead of maintaining the original domain.

The root cause typically lies in how Nginx handles the proxy_pass directive with variables and how backend applications process redirects. When your Tomcat application sends a redirect response, it often includes the full backend path, which Nginx then passes directly to the client.

Here's a complete solution that addresses both the proxy pass and redirect issues:

http {
    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        server_name ~^(www\.)?(?.+)\.example\.com$;
        listen 80;

        location / {
            proxy_set_header Host $host;
            proxy_pass http://backend/prefix-$sub_domain$request_uri;
            proxy_redirect http://$host/prefix-$sub_domain http://$host;
            
            # Additional recommended settings
            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;
        }
    }
}

1. The proxy_pass directive: Using $request_uri ensures the complete URI path is preserved when forwarding to the backend.

2. The proxy_redirect directive: This handles redirect responses from the backend, rewriting them to maintain the original domain structure.

3. Host header: Setting the Host header properly is crucial for applications that do virtual hosting.

The regex-based server_name matching and variable usage in proxy_pass do add minimal overhead, but in practice, the impact is negligible for most applications. The benefits of dynamic routing far outweigh the minor performance cost.

If you need to remove specific parameters (like JSESSIONID) from the request URI, you can use Nginx's map directive or rewrite rules:

map $request_uri $clean_uri {
    default $request_uri;
    ~^(?[^?]*)(?\?.*)?$ $path;
}

# Then use it in your location block:
proxy_pass http://backend/prefix-$sub_domain$clean_uri;

Always verify your setup with curl to see the raw HTTP responses:

curl -v http://www.myapp.example.com

Look for the Location header in 302 responses to ensure redirects are being rewritten correctly.

This configuration provides a flexible solution for mapping wildcard subdomains to backend applications while maintaining clean URLs for end users. The approach works not just for Tomcat but for any backend application that might generate redirects with full paths.