如何在 NGINX 的代理响应中重写 URL

How do I rewrite URLs in a proxy response in NGINX

我习惯将 Apache 与 mod_proxy_html 一起使用,并且正在尝试使用 NGINX 实现类似的功能。具体用例是我在根上下文的服务器上的端口 8080 上的 Tomcat 中有一个管理员 UI 运行:

http://localhost:8080/

我需要在端口 80 上显示它,但我在该主机上的 NGINX 服务器 运行 上有其他上下文,所以想尝试访问它:

http://localhost:80/admin/

我希望以下超级简单的服务器块能够做到这一点,但事实并非如此:

server {
    listen  80;
    server_name screenly.local.akana.com;

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

问题是返回的内容 (html) 包含指向脚本的 URL 和所有在根上下文中访问的样式信息,因此我需要将这些 URL 重写为以 /admin/ 开头/.

如何在 NGINX 中执行此操作?

我们应该先仔细、完整地阅读the documentation on proxy_pass

传递给上游服务器的 URI 取决于 "proxy_pass" 指令是否与 URI 一起使用。 proxy_pass 指令中的尾部斜杠表示 URI 存在且等于 /。缺少尾部斜杠表示缺少 hat URI。

Proxy_pass 与 URI:

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

通过以上,有如下代理:

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

基本上,/some_dir// 取代,将请求路径从 /some_dir/some_subdir/some_file 更改为 /some_subdir/some_file

Proxy_pass 没有 URI:

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

第二个(没有尾部斜杠):代理是这样的:

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

基本上,完整的原始请求路径会在没有更改的情况下传递。


因此,在您的情况下,您似乎应该只删除结尾的斜线以获得您想要的内容。


警告

请注意,只有在 proxy_pass 中不使用变量时,自动重写才有效。如果你使用变量,你应该自己重写:

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

还有其他情况下重写不起作用,这就是必须阅读文档的原因。


编辑

再次阅读您的问题,我似乎没有注意到您只想编辑 html 输出。

为此,您可以使用 sub_filter 指令。像...

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

基本上就是你要替换的字符串和替换字符串

对于具有数据压缩功能的后端服务器,您可能还需要在第一个 "sub_filter" 之前设置以下指令:

proxy_set_header Accept-Encoding "";

否则可能无法正常工作。 对于您的示例,它看起来像:

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;
}

您可以使用以下nginx配置示例:

upstream adminhost {
  server adminhostname:8080;
}

server {
  listen 80;

  location ~ ^/admin/(.*)$ {
    proxy_pass http://adminhost/$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;
  }
}

如果没有超链接需要改写sub_filter, 您可能只使用 proxy_redirect 指令:

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

它根据给定的 'match-rewrite' 规则更改响应的 Location-Header。