How do I rewrite URLs in a proxy response in NGINX

We should first read the documentation on proxy_pass carefully and fully.

The URI passed to upstream server is determined based on whether "proxy_pass" directive is used with URI or not. Trailing slash in proxy_pass directive means that URI is present and equal to /. Absense of trailing slash means hat URI is absent.

Proxy_pass with URI:

location /some_dir/ {
    proxy_pass http://some_server/;
}

With the above, there's the following proxy:

http:// your_server/some_dir/ some_subdir/some_file ->
http:// some_server/          some_subdir/some_file

Basically, /some_dir/ gets replaced by / to change the request path from /some_dir/some_subdir/some_file to /some_subdir/some_file.

Proxy_pass without URI:

location /some_dir/ {
    proxy_pass http://some_server;
}

With the second (no trailing slash): the proxy goes like this:

http:// your_server /some_dir/some_subdir/some_file ->
http:// some_server /some_dir/some_subdir/some_file

Basically, the full original request path gets passed on without changes.


So, in your case, it seems you should just drop the trailing slash to get what you want.


Caveat

Note that automatic rewrite only works if you don't use variables in proxy_pass. If you use variables, you should do rewrite yourself:

location /some_dir/ {
  rewrite    /some_dir/(.*) /$1 break;
  proxy_pass $upstream_server;
}

There are other cases where rewrite wouldn't work, that's why reading documentation is a must.


Edit

Reading your question again, it seems I may have missed that you just want to edit the html output.

For that, you can use the sub_filter directive. Something like ...

location /admin/ {
    proxy_pass http://localhost:8080/;
    sub_filter "http://your_server/" "http://your_server/admin/";
    sub_filter_once off;
}

Basically, the string you want to replace and the replacement string


You may also need the following directive to be set before the first "sub_filter" for backend-servers with data compression:

proxy_set_header Accept-Encoding "";

Otherwise it may not work. For your example it will look like:

location /admin/ {
    proxy_pass http://localhost:8080/;
    proxy_set_header Accept-Encoding "";
    sub_filter "http://your_server/" "http://your_server/admin/";
    sub_filter_once off;
}

You can use the following nginx configuration example:

upstream adminhost {
  server adminhostname:8080;
}

server {
  listen 80;

  location ~ ^/admin/(.*)$ {
    proxy_pass http://adminhost/$1$is_args$args;
    proxy_redirect off;
    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-Host $server_name;
  }
}