我有一个使用CherryPy的WSGI应用程序使用uWSGI在ngnix服务器后面托管。
我希望应用程序本身“可移植”。也就是说,应用程序不应该知道或关心它映射到的URL,如果映射到多个不同的URL,甚至应该工作。我想通过将URL映射信息保存在一个地方来DRY。不幸的是,我发现这样做的唯一方法是使用uwsgi_modifier 30
,has been called an ugly hack。我可以避免这种黑客攻击吗?
就目前而言,我创建了一个名为sample
的小应用程序来演示我的问题。
ngnix配置如下所示:
location /sample/ {
uwsgi_pass unix:/run/uwsgi/app/sample/socket;
include uwsgi_params;
uwsgi_param SCRIPT_NAME /sample;
uwsgi_modifier1 30;
}
/etc/uwsgi/apps-enabled/sample.js
中的uwsgi配置:
{
"uwsgi": {
"uid": "nobody",
"gid": "www-data",
"module": "sample:app"
}
}
......和应用程序本身:
#!/usr/bin/python
import cherrypy
class Root(object):
@cherrypy.expose
def default(self, *path):
return "hello, world; path=%r\n" % (path,)
app = cherrypy.Application(Root(), script_name=None)
有效:
/sample
)仅出现在一个位置:在ngnix配置文件中。该应用程序没有看到该前缀而不必担心它,它只收到/sample
后出现的内容:
$ curl http://localhost/sample/
hello, world; path=()
$ curl http://localhost/sample/foo
hello, world; path=('foo',)
$ curl http://localhost/sample/foo/bar
hello, world; path=('foo', 'bar')
为了激发我的问题的原因,让我们说我有一个应用程序的开发版本。我可以创建第二个uwsgi应用程序并将其指向源代码的不同副本,向指向新uwsgi应用程序的ngnix添加额外的location /sample.test/ { ... }
,并使用备用URL对其进行破解而不影响生产版本。
但是它使用uwsgi_modifier1 30
,这应该是一个丑陋的黑客:
http://uwsgi-docs.readthedocs.org/en/latest/Nginx.html
注意:古老的uWSGI版本用于支持所谓的“uwsgi_modifier1 30”方法。不要做。这是一个非常难看的黑客
现在,我可以这样做:
location /something/ {
uwsgi_pass unix:/run/uwsgi/app/sample/socket;
include uwsgi_params;
}
......而这......
{
"uwsgi": {
"uid": "nobody",
"gid": "www-data",
"pythonpath": "", # no idea why I need this, btw
"mount": "/something=sample:app",
"manage-script-name": true
}
}
但它要求我在2个地方而不是1处对路径(/something
)进行硬编码。我可以避免吗?或者我应该坚持使用uwsgi_modifier1 30
?
答案 0 :(得分:0)
我的回答是关于简化事情的,因为以下内容和配置量表明了一件事 - 过度杀伤。
CherryPy ⇐ WSGI ⇒ uWSGI ⇐ uwsgi ⇒ Nginx ⇐ HTTP ⇒ Client
CherryPy有生产就绪的服务器,本地说HTTP。不需要中间协议,即WSGI。对于低流量,您可以单独使用它。对于前面有Nginx的高流量,例如:
CherryPy ⇐ HTTP ⇒ Nginx ⇐ HTTP ⇒ Client
CherryPy有一个应用程序的概念,你可以serve several applications使用一个CherryPy实例。 CherryPy也可以提供其他WSGI applications。最近我回答related question。
您正在谈论的可移植性本身由CherryPy支持。这意味着您可以将应用程序安装到给定的路径前缀,并且没有其他任何内容可以配置(好吧,只要您使用cherrypy.url
构建URL,并且通常记住应用程序可以挂载到不同的路径前缀)。
server.py
#!/usr/bin/env python3
import cherrypy
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}
# proxy tool is optional
stableConf = {'/': {'tools.proxy.on': True}}
develConf = {'/': {'tools.proxy.on': True}}
class AppStable:
@cherrypy.expose
def index(self):
return 'I am stable branch'
class AppDevel:
@cherrypy.expose
def index(self):
return 'I am development branch'
cherrypy.config.update(config)
cherrypy.tree.mount(AppStable(), '/stable', stableConf)
cherrypy.tree.mount(AppDevel(), '/devel', develConf)
if __name__ == '__main__':
cherrypy.engine.signals.subscribe()
cherrypy.engine.start()
cherrypy.engine.block()
server.conf (可选)
server {
listen 80;
server_name localhost;
# settings for serving static content with nginx directly, logs, ssl, etc.
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}