django - uwsgi_pass 不转发 SCRIPT_NAME 标头
问题描述
我正在尝试使我的 Web 应用程序(基于 Django/wsgi)可从主域的某个子文件夹中使用。我在我的应用程序和静态文件中使用 docker,所以我的服务器上有主 nginx 作为反向代理,“nginx”容器中的另一个 nginx 为我的应用程序和 uWSGI 路由内容,第二个容器为实际的 Django 数据提供服务
而且我希望我的应用程序可以在外部使用myserver.com/mytool
,同时我不想mytool
在我的应用程序的任何地方硬编码。通常SCRIPT_NAME
header 用于这种类型的东西,所以这里是主机上的 nginx 配置:
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 配置:
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
}
}
使用此配置,我希望我的 Django 应用程序收到 SCRIPT_NAME 标头,但显然它没有。
同时,如果我定义自定义标头,proxy_set_header X-something something;
那么它会正确转发,我可以从 Django 中看到它。
我应该如何通过SCRIPT_NAME
以避免代码中的路径硬编码?
解决方案
这里有两个问题。
首先是 nginx 认为包含下划线的SCRIPT_NAME
标头是无效的,因此容器中的 nginx 不接受标头,因为从 nginx 的角度来看它是无效的。幸运的是,nginx 指令underscores_in_headers可以提供帮助。
只需添加underscores_in_headers on;
到Docker 内server
的 nginx 部分(而不是主机)。
当这里完成时,另一个问题是 - nginx 转发HTTP
在其名称前面附加的标头。所以现在从 Django 方面你会看到HTTP_SCRIPT_NAME
而不是SCRIPT_NAME
. uwsgi_param SCRIPT_NAME $http_script_name;
但是,对我们来说幸运的是,再次在 Docker 内部的 nginx 中使用 line 可以很容易地修复它。
因此,Docker 中的最终 nginx 配置应如下所示:
server {
underscores_in_headers on; # <---- (1)
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
uwsgi_param SCRIPT_NAME $http_script_name; # <--- (2)
}
}
在 Djangosettings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/static'
# Bug in Django of not using SCRIPT_NAME header...
# See https://code.djangoproject.com/ticket/25598
# Let's implement dirty workaround for now
if os.getenv('SCRIPT_NAME'):
STATIC_URL = os.getenv('SCRIPT_NAME') + STATIC_ROOT
推荐阅读
- android - 在活动之间切换时看不到屏幕上的活动
- javascript - api调用在其本地主机时有效,但在部署到firebase后不起作用
- excel - 无法在 excel vba 中关闭幽灵项目
- pandas - 我不明白这条线有什么问题
- sql - 使用数据中的间隙运行 Sum
- visual-studio - 为 azure 函数实现不记名令牌身份验证
- python - 基于另一列连接节点列
- javascript - PayPal 智能按钮和 REST Checkout SDK - SyntaxError:JSON 输入意外结束或预期传递订单 ID
- tensorflow - Google Cloud Automl 对象检测培训
- reactjs - 无法在 Dusk 中使用 sanctum 进行身份验证