具有子请求重定向的 nginx 删除查询参数

nginx with sub-request redirection removes query params

我有一个测试应用程序,我通过向烧瓶后端发出内部 /auth 子请求来授权它。

授权通过 google 登录 进行,一旦授权,它就会返回重定向到客户端要求的实际应用程序。

不过,我在这里遇到了一个问题。如果客户端在原始 URL 中传递了多个查询参数,之后将被剥离。

例如:

127.0.0.1/test/?query1=val1&query2=val2&query3=val3

变成

127.0.0.1/test/?query1=val1

基本上 $request_uri 不包含最初传递的所有查询参数。 URL编码是罪魁祸首?

下面是我的 Nginx 配置文件。

worker_processes 1;
daemon off;
error_log stderr debug;

events {
    worker_connections 1024;
}

http {
server {
    listen 80;
    server_name  _;

    proxy_set_header Host $host:80;
    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;

    location ^~ / {
        proxy_pass http://127.0.0.1:8010/;
    }

    # Internal auth check endpoint.
    location = /auth {
        internal;
        proxy_pass http://127.0.0.1:8010/auth;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }

    location ^~ /test/ {
        # Internal sub-request auth check before serving the endpoint.
        auth_request /auth;
        proxy_pass http://127.0.0.1:8011/;

        # Redirect to @login if 401 from /auth.
        error_page 401 @login;
    }

    # Catch if 401/unauthorized and redirect for login
    location @login {
        return 302 /authorize?next=$request_uri;
    }
}
}

请帮忙。

经过2天的研究nginx,终于有了自己的解决方案。 :D

当我将每个传入请求传递给 /auth 时,我在 auth 后端(在我的例子中是 Flask 应用程序)中对 url 进行了编码。 通过像这样更新 headers 将编码的 url 发送回 nginx。

@app.route('/auth')
def auth():
    if not has_valid_cookies():
        resp = flask.Response("", status=401)
        resp.headers['X-Original-URI'] = url_parse.quote(
            flask.request.headers.get('X-Original-URI', '/')
        )
        return resp
    else:
        return flask.jsonify(success=True)

nginx conf 变成如下所示,我将 X-Original-URI 和原始 request_uri 值发送回后端,在那里对其进行编码并像这样保存编码值:

auth_request_set $next_uri $upstream_http_X_Original_URI;

$next_uri 持有编码的原始请求 url.

    location = /auth {
        internal;
        proxy_pass http://127.0.0.1:8010/auth;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }

    location ^~ /test/ {
        # Internal sub-request auth check before serving the endpoint.
        auth_request /auth;
        auth_request_set $next_uri $upstream_http_X_Original_URI;
        proxy_pass http://127.0.0.1:8011/;

        # Redirect to @login if 401 from /auth.
        error_page 401 @login;
    }

    # Catch if 401/unauthorized and redirect for login
    location @login {
        return 302 /authorize?next=$next_uri;
    }