Complete Guide to URL Rewriting in NGINX Proxy Responses

Nov 26, 2025 · Programming · 13 views · 7.8

Keywords: NGINX | reverse_proxy | URL_rewriting

Abstract: This article provides an in-depth exploration of URL rewriting mechanisms in NGINX reverse proxy configurations. By analyzing the URI handling behavior of the proxy_pass directive, it explains the differences between configurations with and without URIs and their impact on upstream server request paths. The article also introduces methods for modifying HTML response content using the sub_filter module and demonstrates through practical cases how to expose applications running in Tomcat root context via the /admin path. Covering configuration examples, common pitfalls, and solutions, it offers comprehensive technical reference for developers.

NGINX Proxy Fundamentals and URI Handling Mechanism

In NGINX reverse proxy configuration, the behavior of the proxy_pass directive depends on whether the target address includes a URI. Understanding this mechanism is crucial for correctly implementing URL rewriting.

When proxy_pass includes a URI (e.g., ending with a slash), NGINX replaces the matched location path with the specified URI. For example, the configuration:

location /admin/ {
    proxy_pass http://localhost:8080/;
}

will proxy the request http://localhost/admin/page.html to http://localhost:8080/page.html, where /admin/ is replaced by /.

Conversely, if proxy_pass does not include a URI:

location /admin/ {
    proxy_pass http://localhost:8080;
}

the request http://localhost/admin/page.html is fully passed to http://localhost:8080/admin/page.html, leaving the path unchanged.

Response Content Rewriting Techniques

When upstream applications return HTML with absolute path resource references, merely adjusting the request path may be insufficient. For instance, a Tomcat application runs in the root context, but its HTML references <script src="/script.js"></script>; these URLs would point to incorrect paths when accessed via the /admin/ proxy.

In such cases, the sub_filter module can be used to dynamically modify response content:

location /admin/ {
    proxy_pass http://localhost:8080/;
    sub_filter "href=\"/" "href=\"/admin/";
    sub_filter "src=\"/" "src=\"/admin/";
    sub_filter_once off;
}

This configuration replaces all href="/..." and src="/..." with href="/admin/..." and src="/admin/...", ensuring resources load correctly. sub_filter_once off ensures all matches are replaced.

Advanced Rewriting Scenarios and Considerations

In variable-based proxy or complex path mapping scenarios, combining the rewrite directive may be necessary:

location /admin/ {
    rewrite ^/admin/(.*)$ /$1 break;
    proxy_pass http://$upstream_server;
}

This configuration first rewrites /admin/xxx to /xxx, then proxies to a dynamic upstream server. Note the break flag prevents further rewriting.

Important limitation: When proxy_pass contains variables, NGINX does not automatically adjust the path; explicit use of rewrite is required.

Practical Deployment Case

Referencing real deployment needs, exposing a Tomcat admin interface running on port 8080 via the /admin/ path on port 80:

server {
    listen 80;
    server_name example.com;

    location /admin/ {
        proxy_pass http://localhost:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        
        sub_filter "action=\"/" "action=\"/admin/";
        sub_filter "href=\"/" "href=\"/admin/";
        sub_filter "src=\"/" "src=\"/admin/";
        sub_filter_once off;
    }
}

This configuration not only handles path mapping but also ensures the upstream application receives correct host information via request headers and comprehensively covers URL references in HTML through multiple sub_filter directives.

Performance and Compatibility Considerations

Using sub_filter increases CPU overhead as it requires scanning and modifying response content. In production environments, assess its performance impact and consider alternatives such as having the upstream application generate correct URLs directly if necessary.

For modern single-page applications (SPAs), handling dynamically generated URLs in JavaScript may require more complex content replacement rules or application-layer adaptations.

By deeply understanding NGINX's proxy mechanisms and content modification capabilities, developers can flexibly build proxy architectures that meet various routing needs while maintaining transparent access to applications.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.