Flask url_for 没有在 docker/docker-compose 下组成正确的 url
Flask url_for doesn't compose correct url under docker/docker-compose
我在 Docker 容器 运行 中有一个 Flask 应用程序 运行。当我使用 url_for
为 API 创建外部 url 时,它 returns docker 服务名称而不是绝对路径。
例如
endpoint = url_for('api_v1.get_me_the_data', sn=123,
_external=True, _scheme="https")
returns 类似于 https://app-primary:8000/api/v1/devices/123
。
其他详情:
- 运行 在 Nginx 反向代理后面使用 Gunicorn
我试过 SERVER_NAME
,但没有骰子。有没有简单的方法来解决这个问题?或者我应该为 url_for
编写一个包装函数吗?
由于您在容器内以及 Nginx 后面有 python 应用程序,因此您可能需要使用 ProxyFix,它会做两件事:
- 通过阅读
REMOTE_ADDR
获取客户端 IP 而不是 nginx 容器 IP
- 通过阅读设置主机名
HTTP_HOST
接下来您需要确保 nginx 发送这些 Headers:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
我有类似的问题。我正在使用 uwsgi 提供烧瓶应用程序,在另一个容器中与 nginx 交谈。我的密码重置功能发送了 links,其中包含容器名称而不是域名。
尝试使用 test_request_contest 和 'SERVER_NAME' 配置变量但惨遭失败。 link 仍在本地主机上。
最终对我有用的是一种快速(非常)肮脏的方法:
def create_external_link(link):
# splits after 'http(s)'
linkParts = link.split("//")
linkLeft = linkParts[0]
linkRight = linkParts[1]
# from the right part (after 'http://') take whats after 'containerName/' doing only one split
linkRight = linkRight.split("/",1)[1]
fullLink = linkLeft + '//example.com/' + linkRight
return fullLink
然后在创建 link 之前将其进一步传递给例如邮件模板:
link = create_external_link(url_for('blueprint.endpoint', **kwargs, _external=True))
一旦找到更好的解决方案,请尽快使用,这是一个丑陋的 hack。
我在 Docker 容器 运行 中有一个 Flask 应用程序 运行。当我使用 url_for
为 API 创建外部 url 时,它 returns docker 服务名称而不是绝对路径。
例如
endpoint = url_for('api_v1.get_me_the_data', sn=123,
_external=True, _scheme="https")
returns 类似于 https://app-primary:8000/api/v1/devices/123
。
其他详情:
- 运行 在 Nginx 反向代理后面使用 Gunicorn
我试过 SERVER_NAME
,但没有骰子。有没有简单的方法来解决这个问题?或者我应该为 url_for
编写一个包装函数吗?
由于您在容器内以及 Nginx 后面有 python 应用程序,因此您可能需要使用 ProxyFix,它会做两件事:
- 通过阅读
REMOTE_ADDR
获取客户端 IP 而不是 nginx 容器 IP
- 通过阅读设置主机名
HTTP_HOST
接下来您需要确保 nginx 发送这些 Headers:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
我有类似的问题。我正在使用 uwsgi 提供烧瓶应用程序,在另一个容器中与 nginx 交谈。我的密码重置功能发送了 links,其中包含容器名称而不是域名。 尝试使用 test_request_contest 和 'SERVER_NAME' 配置变量但惨遭失败。 link 仍在本地主机上。 最终对我有用的是一种快速(非常)肮脏的方法:
def create_external_link(link):
# splits after 'http(s)'
linkParts = link.split("//")
linkLeft = linkParts[0]
linkRight = linkParts[1]
# from the right part (after 'http://') take whats after 'containerName/' doing only one split
linkRight = linkRight.split("/",1)[1]
fullLink = linkLeft + '//example.com/' + linkRight
return fullLink
然后在创建 link 之前将其进一步传递给例如邮件模板:
link = create_external_link(url_for('blueprint.endpoint', **kwargs, _external=True))
一旦找到更好的解决方案,请尽快使用,这是一个丑陋的 hack。