这很长。 tl; dr在结尾。
因此,我正在学习如何使用python。尽管我在其他语言方面有丰富的经验,所以每当我看到适合自己的东西时,我就会跳入深渊。这可能是我的错误,但是肯定会更有趣。
我正在使用 Ubuntu 16.04 LTS。
python3 已安装!其版本描述如下:
python3 --version
:Python 3.5.2
我还安装了 uwsgi 。
python3 -m pip show uwsgi | grep Location
:Location: /home/user/.local/lib/python3.5/site-packages
uwsgi --version
:2.0.17.1
我创建了一个证书颁发机构,并将其作为受信任的根安装到我的浏览器中。
我已经安装了nginx。 Default.conf有两个server
块:一个被配置为提供localhost证书,另一个为我的工作站的标准主机名提供第二个证书。这似乎正常工作(使用Firefox访问https://localhost/
会连接并显示404页面,因为没有静态内容,并且我删除了nginx安装的index.html)。在每个服务器块的内部,我包括另一个文件,该文件通过UNIX域套接字配置WSGI后端。这似乎也可以正常工作:运行wtf
的基本uwsgi进程可以提供我期望的数据。
/etc/nginx/conf.d/default.conf
:
server {
listen 127.0.0.1:80 default_server;
listen [::1]:80 default_server;
listen 127.0.0.1:443 default_server ssl http2;
listen [::1]:443 default_server ssl http2;
ssl_certificate /etc/nginx/sites-certs/localhost.fullchain.pem;
ssl_certificate_key /etc/nginx/sites-certs/localhost.key.pem;
server_name localhost;
location / {
return 444;
root /usr/share/nginx/html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
include sites/ftls.conf;
}
server {
listen 0.0.0.0:80;
listen [::]:80;
listen 0.0.0.0:443 ssl http2;
listen [::]:443 ssl http2;
server_name my.workstation.internal.com;
ssl_certificate /etc/nginx/sites-certs/my.workstation.internal.com.fullchain.pem;
ssl_certificate_key /etc/nginx/sites-certs/my.workstation.internal.com.key.pem;
include sites/ftls.conf;
}
/etc/nginx/sites/ftls.conf
:
location ~ /ftls/ {
rewrite /ftls/(.*) /$1 break;
include uwsgi_params;
uwsgi_pass unix:/home/user/dev/mytest/py/www/backend.sock;
}
/home/user/dev/mytest/py/www/wtf
:
#!/usr/bin/env python3
import uwsgi
import wsgiref.util
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return "application()\n\n{}\nHELLO WORLD\n{}\n{}\n".format(
env,
wsgiref.util.request_uri(env),
wsgiref.util.application_uri(env)
).encode("utf-8")
然后我通过在 bash 中调用以下内容来开始 uwsgi
:
cd ~/dev/mytest/py/www; uwsgi --uwsgi-socket ./backend.sock --wsgi-file ./wtf
然后,在Firefox中,打开https://localhost/ftls/
。我看到application()
,然后是环境变量!是的!
好的,很酷,所以我在读the documentation for uWSGI。如果我正确理解它,可以让 uwsgi 将不同的URL端点路由到不同的python可调用对象。听起来很方便!所以我尝试了一下,但似乎没有用。这是我尝试过的
我不知道django.core.handlers.wsgi.WSGAHandler()
的作用,但看起来它接管了我的应用程序。我不希望我的申请被接管!所以我这样尝试了:
#!/usr/bin/env python3
import uwsgi
import wsgiref.util
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return "application()\n\n{}\nHELLO WORLD\n{}\n{}\n".format(
env,
wsgiref.util.request_uri(env),
wsgiref.util.application_uri(env)
).encode("utf-8")
def wtfapp(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return "wtfapp()\n\n{}".format(env).encode("utf-8")
uwsgi.applications = {
'': application,
'/wtf': wtfapp
}
访问https://localhost/ftls/
后,我仍然被发送到application()
。但是,当我去https://localhost/ftls/wtf
时,我 也 仍然被发送到application()
。嗯?
好的,所以我注意到,尽管在nginx的配置中使用了rewrite
子句,uwsgi
仍会将GET登录到/ftls/
。奇怪的。有解决办法吗?是什么原因造成的?无论如何,我尝试更新uwsgi.applications
来查看。
uwsgi.applications = {
'': application,
'/wtf': wtfapp,
'/ftls': wtfapp,
'/ftls/wtf': wtfapp
}
尽管如此,所有端点仍指向application()
好的,所以我读了一些文档,上面写着:
> Passing this Python module name (that is, it should be importable and without the .py extension)
老实说,我不知道这意味着什么。我的wtf
python文件没有.py
扩展名。可导入是什么意思?
它还会继续提及
> to uWSGI’s module / wsgi option, uWSGI will search the uwsgi.applications dictionary for the URL prefix/callable mappings.
好吧,我正在通过--wsgi-file
将python文件传递给uwsgi。这和--wsgi
不同吗?
uwsgi --help | grep \\-\\-wsgi
说:
--wsgi-file load .wsgi file
-w|--wsgi load a WSGI module
选项的帮助文本明显不同,因此另一个选项可能有用吗?如果我终止uwsgi
并改用该选项运行它,那么我会发现事情做得不好:
uwsgi --uwsgi-socket ./backend.sock --wsgi ./wtf
> blah blah blah log messages and junk
> ...
> ImportError: No module named './wtf'
> unable to load app 0 (mountpoint='') (callable not found or import error)
> *** no app loaded. going in full dynamic mode ***
> ...
> blah
而且,当我尝试通过浏览器进行连接时,我看到一条日志消息,内容为--- no python application found, check your startup logs for errors ---
,浏览器显示了一个非常普通的Internal Server Error
页面。没有错误信息发送到浏览器。天哪,确定很方便(讽刺)。不仅如此,为什么uwsgi
在明显出现配置错误时不立即停止运行?它被告知要加载某些内容,但无法加载它,因此它继续报告未加载任何应用程序,并进入了完全动态模式。那是 极不合常规的 ,肯定是我还没有准备好挖的另一个兔子洞。
但是,嘿,一个不同的症状,一个不同的错误消息,也许这是一件好事。
那么,这里所说的WSGI模块是什么?我尝试阅读documentation for Python Modules。它说:
> A module is a file containing Python definitions and statements.
听起来对我来说,我的wtf
代码就是这样。所以我一直在读书。
> The file name is the module name with the suffix .py appended.
除了,这是uwsgi文档所说的相反。 uwsgi再次声明it should be ... without the .py extension
。我很困惑。无论如何,我将假定他们在谈论同一件事。继续说,键入import wtf
应该可以在python3 shell中进行。 Python3说:ImportError: No module named 'wtf'
。如果我将文件重命名为wtf.py
,则python3会给出另一个错误,ImportError: No module named 'uwsgi'
。
奇怪。但是我似乎记得,我只是因为an obscure issue on Github而发现了uwsgi
可执行文件。我花了小时的时间在Google搜索中找到了那个,错误消息是一样的!
所以,我假设如果我离开了名为wtf.py
的文件,那么uwsgi
(可执行文件)应该使uugi(该模块)可用于Python代码,并且一切都会好起来!
uwsgi --uwsgi-socket ./backend.sock --wsgi ./wtf
这个人说:ImportError: No module named './wtf'
好的,所以也许它不喜欢相对路径。
uwsgi --uwsgi-socket ./backend.sock --wsgi wtf
这个人说:
> found a multiapp module...
> the app mountpoint must be a string
哦,我知道这个错误!我在another Github issue上看到了它!
所以那里的解决方案似乎很适合我的情况:
uwsgi.applications = {
b'': application,
b'/wtf': wtfapp,
b'/ftls': wtfapp,
b'/ftls/wtf': wtfapp
}
现在,当我运行uwsgi --uwsgi-socket ./backend.sock --wsgi wtf
时,我看到:
> WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x22cf2b0 pid: 12553 (default app)
> WSGI app 1 (mountpoint='/ftls') ready in 0 seconds on interpreter 0x22cf2b0 pid: 12553
> WSGI app 2 (mountpoint='/wtf') ready in 0 seconds on interpreter 0x22cf2b0 pid: 12553
> WSGI app 3 (mountpoint='/ftls/wtf') ready in 0 seconds on interpreter 0x22cf2b0 pid: 12553
我的天哪!看起来很有希望!
...除了...
:: rageface ::
所有端点仍在浏览器中返回application()
! wtfapp()
仍未被调用 。
因此,在这一点上,我已经尽力尝试了。我敢肯定,我忽略了这件事。任何帮助或见识将不胜感激。
tl;博士,我的问题是:
rewrite
中使用了nginx
指令,uwsgi仍然可以看到完整的URI?uwsgi
看到几个应用程序“挂载点”,但它们似乎都已转到默认应用程序。导致uwsgi
不能将不同的URL路由到不同的python函数定义,我做错了什么?