具有子请求重定向的 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;
}
我有一个测试应用程序,我通过向烧瓶后端发出内部 /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;
}