uwsgi_pass不转发SCRIPT_NAME标头 [英] uwsgi_pass does not forward SCRIPT_NAME header
问题描述
我正在尝试从主域的某些子文件夹中提供我的Web应用程序(基于Django/wsgi). 我将docker用于我的应用程序和静态文件,因此我在服务器上使用了主要的nginx作为反向代理,在"nginx"容器中使用了另一个nginx,用于将我的应用程序的内容和uWSGI路由到第二个容器中,该容器用于提供实际的Django数据
I'm trying to make my web app (Django/wsgi-based) available from some subfolder of the main domain. I'm using docker for my app, and static files, so I have main nginx on my server as reverse proxy, another nginx in "nginx" container which routes the stuff for my app and uWSGI in the second container which serves actual Django data
并且我希望我的应用可以以myserver.com/mytool
的形式在外部使用,与此同时,我不想在应用中的任何地方对mytool
进行硬编码.通常SCRIPT_NAME
标头用于这种类型的东西,因此这是主机上的nginx配置:
And I want my app to be available externally as myserver.com/mytool
, in the same time I do not want to hardcode mytool
anywhere in my app. Usually SCRIPT_NAME
header is used for this type of stuff, so here is nginx configuration on the host:
server {
listen 80; # Just for sake of simplicity, of course in production it's 443 with SSL
location /mytool/ {
proxy_pass http://127.0.0.1:8000/;
include proxy_params;
proxy_set_header SCRIPT_NAME /mytool; # <--- Here I define my header which backend should use
}
}
然后在我的docker-compose
中,我为nginx公开了8000:80,这是内部nginx配置:
Then in my docker-compose
I expose 8000:80 for nginx and here is internal nginx configuration:
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
}
}
通过这种配置,我希望我的Django应用接收到SCRIPT_NAME标头,但显然没有.
With this configuration I would expect that my Django app receives SCRIPT_NAME header, but apparently it does not.
同时,如果我定义自定义标头(如proxy_set_header X-something something;
),则此标头将正确转发,并且可以从Django中看到它.
In the same time if I define custom headers like proxy_set_header X-something something;
then this gets forwarded correctly and I can see it from Django.
我应该如何传递SCRIPT_NAME
以避免在代码中使用路径硬编码?
How should I pass SCRIPT_NAME
to avoid path hardcode in my code?
推荐答案
这里有两个问题.
首先,nginx将包含下划线的标头视为无效,因此SCRIPT_NAME
标头不会被容器中的nginx接受,因为从nginx角度来看,它是无效的.幸运的是,nginx指令 underscores_in_headers 在这里可以提供帮助.
First is that nginx considers headers which contain underscores as invalid, so SCRIPT_NAME
header is not being accepted by nginx in the container because it's invalid from nginx point of view. Luckily, nginx directive underscores_in_headers is here to help.
只需在Docker 内的nginx 的server
部分中添加underscores_in_headers on;
(而不是在主机中).
Just add underscores_in_headers on;
to server
section of nginx inside Docker (not to the host one).
完成此操作后,还有另一个问题-nginx在其名称前面转发在HTTP
之前的标头.因此,现在从Django端您将看到HTTP_SCRIPT_NAME
而不是SCRIPT_NAME
.但是,再次幸运的是,可以再次在Docker内部的nginx中使用uwsgi_param SCRIPT_NAME $http_script_name;
行来轻松修复它.
When this is done here is yet another issue - nginx forwards header prepending HTTP
in front of its name. So now from Django side you will see HTTP_SCRIPT_NAME
instead of SCRIPT_NAME
. But again, luckily for us, it can be easily fixed by using uwsgi_param SCRIPT_NAME $http_script_name;
line in nginx inside Docker again.
因此,Docker内部的最终nginx配置应如下所示:
Thus, final nginx config inside Docker should look like:
server {
underscores_in_headers on; # <---- (1)
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
uwsgi_param SCRIPT_NAME $http_script_name; # <--- (2)
}
}
这篇关于uwsgi_pass不转发SCRIPT_NAME标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!