【问题标题】:How do I rewrite URLs in a proxy response in NGINX如何在 NGINX 的代理响应中重写 URL
【发布时间】:2015-12-09 03:00:46
【问题描述】:

我习惯于将 Apache 与 mod_proxy_html 一起使用,并且正在尝试使用 NGINX 实现类似的功能。具体用例是我在 Tomcat 中在根上下文的服务器上的 8080 端口上运行了一个管理 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 中做到这一点?

【问题讨论】:

    标签: nginx


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      可以使用下面的nginx配置示例:

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

      【讨论】:

      • 为什么会被否决?代码有问题吗?对我来说似乎是一个不错且复杂的解决方案,解决了代理稍后弹出的应用程序的一些警告。不知道为什么proxy_redirect off;。另外我会添加proxy_set_header X-Forwarded-Proto $scheme;
      • > 问题是返回的内容 (html) 包含所有在根上下文中访问的脚本和样式信息的 URL,因此我需要重写这些 URL 以改为以 /admin/ 开头的 /。至少在发布此评论时,它不满足此要求。
      【解决方案3】:

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

      传递给上游服务器的 URI 取决于“proxy_pass”指令是否与 URI 一起使用。 proxy_pass 指令中的尾部斜杠表示 URI 存在且等于 /。没有尾部斜杠意味着不存在帽子 URI。

      带有 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

      没有 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/(.*) /$1 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 会做到的。
      • 我很好奇 nginx 已经在多大程度上重写了输出,难道它不需要至少在链接中重写主机/主机名吗?例如,你不会sub_filter "http://localhost/" "http://localhost/admin/"
      • 为了允许重写text/html mimetype 以外的其他类型,我还必须添加sub_filter_types *;
      • 这个解决方案对我来说发生了一些奇怪的事情。资源(*.js、*.css 等正在获取),但页面无法加载。我希望http://your_server/admin/ 在proxy_pass 期间被解析为http://your_server,但它没有,我在我的应用程序中收到错误react-router /admin/ location did not match any routes,因为我的应用程序对'/admin'一无所知。
      • 非常感谢您对带有URI的proxy_pass的解释,这解决了我的问题(/)
      【解决方案4】:

      对于具有数据压缩的后端服务器,您可能还需要在第一个“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;
      }
      

      【讨论】:

      • 顺便说一句:对于正则表达式检查subs_filter(是的,还有另一个s)。
      猜你喜欢
      • 2018-04-06
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 2013-04-23
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      相关资源
      最近更新 更多