How to make nginx rewrite URIs in HTTP body content

nginxreverse-proxy

This is a follow-on to my earlier question on how to Make nginx reverse proxy 302 redirect to a URI sub-folder instead of root.

I have an nginx proxy server that uses the rewrite and proxy_pass directives to proxy external requests to a URL like https://domain.com/my/web/app/ to an internal LAN server at https://10.0.0.22/. Here's my attempt to represent the translation in ASCII UML:

                                    .-------------.       .------------------.
                                    | Nginx proxy  |      | Local web server |
                                    | (domain.com) |      | (10.0.0.22)      |
                                    '-------------'       '------------------'
                                               |                 |
                                               |                 |
GET https://domain.com/my/web/app/ ----------->|                 |
                                               |---------------->| GET /
                                               |                 |
                                               |<----------------| 302 redirect /login.php
302 redirect /my/web/app/login.php <-----------|                 |
                                               |                 |
GET https://domain.com/my/web/app/login.php -->|                 |
                                               |---------------->| GET /login.php
                                               |                 |
                                               |<----------------| 200
HTML body content (images, CSS, links) <-------|

Here's the actual location block in my nginx configuration file:

location ^~ /my/web/app/
{
    proxy_buffering   off;
    rewrite           /my/web/app/(.*) /$1 break;
    proxy_pass        https://10.0.0.22/;
    proxy_redirect    default;
}

It works great for URI translation between the internal and external URI paths for HTTP requests and responses, but any URIs in the HTML content (body images, CSS, scripts) are not translated.

For example, images with relative paths embedded in the HTML response, with URIs like /images/logo.png, are passed back to the web client and interpreted as https://domain.com/images/logo.png instead of https://domain.com/my/web/app/images/logo.png.

I can understand why this is happening, but it would be wonderful if there was a way to dynamically proxy content as well as requests. Is there a way to get nginx to also convert URIs embedded in the HTML content? Is it possible to dynamically parse and update HTML content as it passes through the proxy server?

Best Answer

The only solution to this that I have found so far is the HttpSubsModule (see also the github page).

The module is not part of the official Nginx sources, so you will probably need to build Nginx yourself to use this module.

Related Question