【问题标题】:Nginx sub_filter for headers用于标头的 Nginx sub_filter
【发布时间】:2019-11-05 15:20:40
【问题描述】:

我想在运行在自己端口上的不同应用程序之前使用 nginx proxy_pass。

所以我有

server {

    listen 443 ssl;
    ssl on;

    ssl_certificate /etc/ssl/certs/self-signed.crt;
    ssl_certificate_key /etc/ssl/private/self-signed.key;

    proxy_intercept_errors on;

    location /app1/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_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-Proto $scheme;
        proxy_http_version 1.1;
        proxy_redirect off;
        proxy_pass http://localhost:1111;
    }

    location /app2/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_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-Proto $scheme;
        proxy_http_version 1.1;
        proxy_redirect off;
        proxy_pass http://localhost:2222;
    }
}

但问题是应用程序本身有重定向,导致 /app1/ 或 /app2/ 消失。

即302 get /page1 将变为 https://example.com/page1 而不是 https://example.com/app1/page1

所以基本上每当有人在 /app1/* 页面上时,总是添加前缀 /app1/。

如果这实际上是完整的域名时不会发生这种情况,那就太好了,因此可以从 /app1/ 页面中的 /app2/ url 加载资源

有什么方法可以通过 Nginx 配置修复,还是只能在应用程序本身中修复?

编辑:

我发现 Nginx 有一个叫做 sub_filter 的函数。

这替换了响应正文中的字符串。

所以: 应用返回:200 "hello world!"

//nginx
sub_filter "world" "moon";

然后浏览器将显示“你好月亮!”

但是我还需要为 302 重定向执行此操作。

标题是否有“sub_filter 等效项”?

EDIT2:

正如 Ivan 所建议的那样,代理重定向应该可以解决问题,但它并没有改变任何东西。 我的 nginx 代码是:

location /app1/ {
    proxy_set_header Accept-Encoding ""; # no compression allowed or next won't work
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_http_version 1.1;
    proxy_redirect off;
    proxy_buffering off;
    proxy_read_timeout 3600;
    proxy_connect_timeout 3600;
    fastcgi_read_timeout 3600s;

    proxy_pass http://localhost:5000/;
    proxy_redirect http://localhost:5000/ /app1/; #also tried full domain
}

至于应用程序,我正在使用这样一个简单的 Flask 应用程序进行测试:

@app.route('/')  
def hello_world(): 
    return redirect("http://localhost:5000/testing", code=302)

浏览器响应头是:

HTTP/1.1 302 FOUND
Server: nginx/1.14.0 (Ubuntu)
Date: Wed, 06 Nov 2019 15:56:24 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Location: http://localhost:5000/testing

【问题讨论】:

  • 如果你尝试proxy_pass http://localhost:1111/app1/;proxy_pass http://localhost:2222/app2/;会发生什么?
  • @IvanShatsky 它返回 404,因为应用程序中没有 /app1/ 路径。
  • 这些重定向是什么样的?它们是 3xx HTTP 代码还是 href 的响应正文?
  • @IvanShatsky 这些是 302 个 http 代码。 href 可以用 sub_filter 完成

标签: nginx nginx-location


【解决方案1】:

针对您的情况使用 proxy_redirect 指令:

proxy_redirect / /app1/;

proxy_redirect / /app2/;

删除任何proxy_redirect off; 指令,因为它会取消同一级别上所有proxy_redirect 指令的效果。

【讨论】:

  • 我认为你应该用proxy_redirect来做是对的。然而,什么都没有改变。我会将我的代码编辑放在问题中。
  • @user3605780 删除 proxy_redirect off; 指令并尝试这个
  • 谢谢!我一直在解决端口问题 - 我在 NAT 之后,无法控制 80,仅使用非标准端口进行 https,并且我的应用程序将重定向发送到 80。您的建议为我指出了正确的重写解决方案响应头:proxy_redirect http://$host/ https://$host:1443/; 请注意,这是一个肮脏的解决方案,不适合生产使用 - 因为您显然应该控制 80(或者更确切地说是服务器的所有端口和其他重要方面)。
猜你喜欢
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 2015-10-31
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 2016-11-09
相关资源
最近更新 更多