You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask配置ProxyFix后仍识别Docker容器名而非真实域名问题

Nginx反向代理下Flask ProxyFix无法替换真实域名问题

我的Nginx和Flask应用运行在同一Docker网络,已为基于Gunicorn的Flask配置Nginx反向代理,并设置ProxyFix修正url_for()生成的路由。目前X-Forwarded-Proto和X-Forwarded-Prefix已生效,但ProxyFix未能将请求的真实域名替换掉proxy_pass中使用的Docker容器名api-service。

使用url_for()生成Google OAuth的redirect_uri时,得到的地址为https://api-service/api/authorize/callback/,被Google拒绝;未配置ProxyFix时地址为http://api-service/authorize/callback。

我怀疑Nginx中$cors_origin未被正确设置,导致X-Forwarded-Host fallback到容器名,但浏览器请求头显示origin、referrer和host均为正确的domain1.com。


相关配置

Nginx配置

http {
    upstream api-service {
        server api-service:5010;
    }

    # Redirect HTTP to HTTPS
    server {
        listen 80;
        listen [::]:80;

        server_name domain1.com domain2.com;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;
        listen [::]:443 ssl;

        http2 on;

        server_name domain1.com;

        location /api/ {
            # Dynamically set the CORS origin based on the incoming request
            set $cors_origin "";

            if ($http_origin ~* (http://localhost:4025|https://domain1.com)) {
                set $cors_origin $http_origin;
            }

            # Add basic CORS headers for all requests
            add_header 'Access-Control-Allow-Origin' $cors_origin always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'Accept, Content-Type, Authorization' always;

            # Handle CORS preflight (OPTIONS) requests
            if ($request_method = OPTIONS) {
                add_header 'Access-Control-Max-Age' 1728000;
                return 204;
            }

            # Handle other requests
            if ($request_method != OPTIONS) {
                add_header 'Access-Control-Allow-Credentials' 'true' always;
            }

            # Proxy to the API service
            proxy_pass http://api-service/;
            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 $cors_origin;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Prefix /api;
            proxy_redirect off;
            proxy_connect_timeout 500s;
            proxy_send_timeout 500s;
            proxy_read_timeout 500s;
        }
    }
}

Flask配置

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1, x_proto=1, x_prefix=1)

OAuth相关代码

authorization_url = client.prepare_request_uri(
   provider_data["authorize_url"],
   redirect_uri=url_for(
      "authorize.oauth2_callback", provider=provider, _external=True
   ),
   scope=provider_data["scopes"],
)

解决方案

问题核心在于Nginx的X-Forwarded-Host设置:你使用$cors_origin传递主机名,但该变量仅在请求包含符合规则的Origin头时才会被赋值,而OAuth授权流程中的后端请求(比如生成redirect_uri的逻辑)可能没有Origin头,导致$cors_origin为空,ProxyFix只能 fallback 到容器名。

步骤1:修正Nginx的X-Forwarded-Host配置

直接使用$host或$http_host传递真实请求域名,替换原有的$cors_origin:

proxy_set_header X-Forwarded-Host $host;
# 若需保留端口信息,可改用$http_host
# proxy_set_header X-Forwarded-Host $http_host;

步骤2:检查Flask的SERVER_NAME配置

如果Flask设置了SERVER_NAME,它会覆盖X-Forwarded-Host的作用,确保不要设置该参数,或设置为真实域名:

# 注释或删除该配置,避免覆盖反向代理传递的主机信息
# app.config['SERVER_NAME'] = 'domain1.com'

内容的提问来源于stack exchange,提问作者MKF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:45:12