nginx - flask+ngix+uwsgi 没有从路由 ubuntu 20 中剥离脚本根目录
问题描述
我希望有人能帮助我。
我正在尝试将一组烧瓶应用程序从 Ubuntu 18 机器重新部署到 ubuntu 20 机器上,但它们的行为与早期部署不同。
它们已成功部署在 Ubuntu 14,16 和 18 上,包括在 Ubuntu 18 部署中从 python 2 到 3 的转换,但 Ubuntu 20 上的最新部署让我完全难过。
它们使用下面描述的配置运行(在 Ubuntu 18 上成功)。在新的 Ubuntu 20 机器上部署时,flask 将路由视为脚本根(以及脚本根),这会导致 404。
当前在 U18 上工作的设置如下(nginx 简化用于测试非 TLS 连接)
在 :9999 上运行的应用程序不在它自己的位置,并且运行良好。
NGINX:
server {
underscores_in_headers on;
listen 80 default_server;
server_name _;
location /.well-known {
root /var/www/html/;
}
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:9999;
}
location /a {
uwsgi_param SCRIPT_NAME /a;
uwsgi_modifier1 30;
include uwsgi_params;
uwsgi_pass 127.0.0.1:10017;
}
}
UWSGI:
[uwsgi]
socket = :10017
plugin = python3
wsgi-file = /home/webmaster/app/run
callable = app
master = true
enable-threads = true
processes = 1
chdir= /home/webmaster/app
uid = www-data
gid = www-data
我将 404 处理程序设置为返回一些 URL 信息,而不是获取应用程序的登录页面,而是使用以下内容获取 404(即 nginx 正在传递给 uwsgi,并且应用程序正在运行)
网址:
http://192.168.0.250/a
输出:
url root http://192.168.0.250/a/
script root /a
request url http://192.168.0.250/a/a
request path /a
request full_path /a?
所以 url_root 和 script_root 是你所期望的,也是我们想要看到的,但是 request_url ( http://192.168.0.250/a/a ) 和 request_path (/a) 不是。为了让所有东西都有自己的位置,request_path 应该是“/”。
我试过的
我提到了以前的问题,特别是这个问题: Q:在子目录 nginx + uwsgi 上服务烧瓶应用程序 和这个问题: A:如何在 nginx 上托管的单个域下托管多个烧瓶应用程序?
我已经尝试了这些帖子中的建议,包括以下 nginx 配置:
超级简单,要求 uwsgi 做更多事情:
location /c {
include uwsgi_params;
uwsgi_pass 127.0.0.1:10017;
}
使用 UWSGI:
[uwsgi]
socket = :10017
plugin = python3
wsgi-file = /home/webmaster/app/run
callable = app
master = true
enable-threads = true
processes = 1
chdir= /home/webmaster/app
uid = www-data
gid = www-data
mount = /a=run
manage-script-name = true
这并没有解决问题
接下来我尝试重写(尝试)并欺骗 uwsgi 认为它在没有脚本根目录的情况下运行
location /b {
rewrite ^/b/(.*) /$1 break;
include uwsgi_params;
uwsgi_pass 127.0.0.1:10017;
}
这也失败了
我也通过了上述问题讨论部分中的建议,虽然大部分工作都在修改脚本根目录,但没有人从路径中删除脚本根目录,从而启用“/start”的烧瓶路由来服务于识别的应用程序的根目录通过www.app.com/a/start
我也知道 uwsgi_modifier1 30; 已折旧,尽管这是这些烧瓶应用程序的首次部署,但这是一个问题。
我还尝试script_name=None
根据以下问题在烧瓶端使用参数:
如何避免 uwsgi_modifier1 30 并保持 WSGI 与我的应用程序位置无关
但到目前为止没有任何效果,我完全被难住了。这可能很简单,但我不知道从哪里看。
最后一件事,这些应用程序以皇帝模式运行,并从命令行运行 uwsgi,无论是作为单独的 .ini 文件,还是作为皇帝文件都没有区别。
uwsgi 作为通过 apt 安装的服务运行,而不是 pip(但在使用 plugin=python3 时似乎运行良好),以防有人遇到过这个问题。
如果可能的话,我想坚持使用 apt 安装。
提前感谢任何可以提供帮助的人。
[编辑中]
这是我试图让烧瓶处理静态路由的 wsgi 文件。应该早点把它包括在内,但这是一个疏忽。
谢谢
#!/usr/bin/python3
from application import app
app.config['SECRET_KEY'] = 'XXXXXXXXXX'
app.config["SESSION_COOKIE_SECURE"] = True
app.config["REMEMBER_COOKIE_SECURE"] = True
app.config["SESSION_COOKIE_HTTPONLY"] = True
app.config["REMEMBER_COOKIE_HTTPONLY"] = True
app.config['APPLICATION_ROOT'] = '/a'
app.static_url_path = '/a'
if __name__ == "__main__":
app.run(debug = True, host= '0.0.0.0', port= 5000)
解决方案
对于其他偶然发现这一点的人:
根据其他问题的建议使用重写,只需注意您使用的表达式是否正确。
这将失败:
location /foo {
rewrite ^/foo/(.*) /$1 break;
uwsgi_param SCRIPT_NAME /foo;
include uwsgi_params;
uwsgi_pass 127.0.0.1:10017;
}
因为它只适用于脚本名称“foo”,在 URL“/foo/bar”处路由“/bar”。/foo 的根目录将失败。
这将起作用:重写 ^/foo(.*) /$1 break;
例如
location /foo {
rewrite ^/foo(.*) /$1 break;
uwsgi_param SCRIPT_NAME /foo;
include uwsgi_params;
uwsgi_pass 127.0.0.1:10017;
}
它将传递脚本名称,并将其从使其工作的请求路径中取出。
问题是重写中的额外“/”。
这是一个简单的错误,我花了很多时间才发现,因为我看不到森林的树木......所以我希望这可以帮助其他人。
推荐阅读
- python - Webscraping - Selenium BeautifulSoup - 通过分页循环
- c# - C# 从 Web API 读取 JSON
- typescript - 从泛型函数创建泛型类型
- ios - iOS 13 上的 AVAssetReferenceRestrictions
- .net - 网页加载间歇性问题,除了来自 Asp.net MVC 的捆绑包外,没有触发 html/js 请求
- javascript - prop-types 在 React Native App 中不起作用
- css - IE11 和 Edge 中奇怪的 CSS3 动画问题
- javascript - 如何 *ngFor 超过一组 ngModel 可绑定属性
- oracle - 如何使用 Oracle PL/SQL 声明、填充和使用变量
- azure - Azure 服务总线队列被意外删除