如何在 Django 设置中指定显式主机名?
How to specify explicit host name in Django settings?
我正在开发一个通过多个 Docker 容器运行的 Django 项目,Django 站点本身是一个 Nginx 容器将请求转发到的中间件。为了测试 Nginx 容器的端口 80 映射到 8080。因此我去 http://localhost:8080/ 并查看 Django 网站。
我遇到的问题是重定向 URL(由 social-auth-app-django
包为 Google 登录构建)使用 http://localhost
作为基础而不是 http://localhost:8080
.
设置 LOGIN_REDIRECT_URL
不是我要找的,因为它发生在 身份验证成功之后。
我试过 SOCIAL_AUTH_LOGIN_REDIRECT_URL
,它是 mentioned somewhere,但那是旧版本,似乎不再执行任何操作。
由于 Django 对所有绝对 URL 使用 build_absolute_uri,因此必须有一种方法来覆盖基 URL and/or host?
TL;DR = Nginx 没有 Docker-mapped 端口的概念,需要 hard-coded.
类似问题:https://serverfault.com/questions/577370/how-can-i-use-environment-variables-in-nginx-conf
Django 要求 HTTP 请求 headers 包含主机所需的信息(下面的代码片段)。这种情况需要从Nginx传入:
location / {
proxy_pass http://web:7000;
proxy_set_header Host $host:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
注意端口的不幸 hard-coding:$host:8080
。 "outer" 问题是 Nginx 容器的端口使用 Docker 映射到 8080 (-p 80:8080
) 因此它 不知道 它是实际上 运行 在端口 8080 上; Nginx 在端口 80 上将自己检测为 运行。
是 SOCIAL_AUTH_LOGIN_REDIRECT_URL
的 Django 设置,但像这样指定它:
SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'http://localhost:8080/complete/google-oauth2/'
尝试通过 Google 进行身份验证时导致此情况发生:
AuthMissingParameter at /complete/google-oauth2/
Missing needed parameter state
Request Method: GET
Request URL: http://localhost:8080/complete/google-oauth2/
Django Version: 2.1.5
Exception Type: AuthMissingParameter
Exception Value:
Missing needed parameter state
Exception Location: /usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py in validate_state, line 88
Python Executable: /usr/local/bin/python
Python Version: 3.6.10
因此我目前唯一的解决方案是在构建 Docker 图像时将端口烘焙到 Nginx 配置中。
Django 2.1.5版获取主机代码:
def _get_raw_host(self):
"""
Return the HTTP host using the environment or request headers. Skip
allowed hosts protection, so may return an insecure host.
"""
# We try three options, in order of decreasing preference.
if settings.USE_X_FORWARDED_HOST and (
'HTTP_X_FORWARDED_HOST' in self.META):
host = self.META['HTTP_X_FORWARDED_HOST']
elif 'HTTP_HOST' in self.META:
host = self.META['HTTP_HOST']
else:
# Reconstruct the host using the algorithm from PEP 333.
host = self.META['SERVER_NAME']
server_port = self.get_port()
if server_port != ('443' if self.is_secure() else '80'):
host = '%s:%s' % (host, server_port)
return host
我正在开发一个通过多个 Docker 容器运行的 Django 项目,Django 站点本身是一个 Nginx 容器将请求转发到的中间件。为了测试 Nginx 容器的端口 80 映射到 8080。因此我去 http://localhost:8080/ 并查看 Django 网站。
我遇到的问题是重定向 URL(由 social-auth-app-django
包为 Google 登录构建)使用 http://localhost
作为基础而不是 http://localhost:8080
.
设置 LOGIN_REDIRECT_URL
不是我要找的,因为它发生在 身份验证成功之后。
我试过 SOCIAL_AUTH_LOGIN_REDIRECT_URL
,它是 mentioned somewhere,但那是旧版本,似乎不再执行任何操作。
由于 Django 对所有绝对 URL 使用 build_absolute_uri,因此必须有一种方法来覆盖基 URL and/or host?
TL;DR = Nginx 没有 Docker-mapped 端口的概念,需要 hard-coded.
类似问题:https://serverfault.com/questions/577370/how-can-i-use-environment-variables-in-nginx-conf
Django 要求 HTTP 请求 headers 包含主机所需的信息(下面的代码片段)。这种情况需要从Nginx传入:
location / {
proxy_pass http://web:7000;
proxy_set_header Host $host:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
注意端口的不幸 hard-coding:$host:8080
。 "outer" 问题是 Nginx 容器的端口使用 Docker 映射到 8080 (-p 80:8080
) 因此它 不知道 它是实际上 运行 在端口 8080 上; Nginx 在端口 80 上将自己检测为 运行。
是 SOCIAL_AUTH_LOGIN_REDIRECT_URL
的 Django 设置,但像这样指定它:
SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'http://localhost:8080/complete/google-oauth2/'
尝试通过 Google 进行身份验证时导致此情况发生:
AuthMissingParameter at /complete/google-oauth2/
Missing needed parameter state
Request Method: GET
Request URL: http://localhost:8080/complete/google-oauth2/
Django Version: 2.1.5
Exception Type: AuthMissingParameter
Exception Value:
Missing needed parameter state
Exception Location: /usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py in validate_state, line 88
Python Executable: /usr/local/bin/python
Python Version: 3.6.10
因此我目前唯一的解决方案是在构建 Docker 图像时将端口烘焙到 Nginx 配置中。
Django 2.1.5版获取主机代码:
def _get_raw_host(self):
"""
Return the HTTP host using the environment or request headers. Skip
allowed hosts protection, so may return an insecure host.
"""
# We try three options, in order of decreasing preference.
if settings.USE_X_FORWARDED_HOST and (
'HTTP_X_FORWARDED_HOST' in self.META):
host = self.META['HTTP_X_FORWARDED_HOST']
elif 'HTTP_HOST' in self.META:
host = self.META['HTTP_HOST']
else:
# Reconstruct the host using the algorithm from PEP 333.
host = self.META['SERVER_NAME']
server_port = self.get_port()
if server_port != ('443' if self.is_secure() else '80'):
host = '%s:%s' % (host, server_port)
return host