首页 > 解决方案 > 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)

标签: nginxflaskuwsgiubuntu-20.04

解决方案


对于其他偶然发现这一点的人:

根据其他问题的建议使用重写,只需注意您使用的表达式是否正确。

这将失败:

 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;
 }

它将传递脚本名称,并将其从使其工作的请求路径中取出。

问题是重写中的额外“/”。

这是一个简单的错误,我花了很多时间才发现,因为我看不到森林的树木......所以我希望这可以帮助其他人。


推荐阅读