我想使用CherryPy的独立实例从单个服务器提供多个域。我希望每个域都可以从一个完全独立的CherryPy应用程序中提供,每个应用程序都有自己的配置文件。
我玩cherrypy.dispatch.VirtualHost
,但似乎无法单独配置文件。
一个类似的问题(here)表明这很难,但没有解释为什么和可能是因为没有人回答这个问题。
此CherryPy recipe for multiple apps显示了如何使用单独的配置文件加载多个沙盒应用,但看起来它们是在同一个域中提供的。
我可以理解答案可能是“使用CherryPy作为Nginx或Apache背后的WSGI服务器”,但我宁愿只在这个特定的服务器上处理CherryPy。
答案 0 :(得分:1)
在同一个回购中,有vhost recipe。但是它使用共享应用程序。我没有看到让cherrypy.dispatch.VirtualHost
使用单独安装的应用的方法。这是因为在调度程序调用之前设置了cherrypy.serving.request.app
。说你有以下。
hostmap = {
'api.domain.com' : '/app1',
'www.domain.com' : '/app2'
}
cherrypy.tree.mount(App1(), '/app1', appConfig1)
cherrypy.tree.mount(App2(), '/app2', appConfig2)
所有cherrypy.dispatch.VirtualHost
做的是将域前缀添加到当前网址,例如请求http://www.domain.com/foo
将导致/app2/foo/
作为内部路径发送给下一个通常为cherrypy.dispatch.Dispatcher
的调度程序。然而,后者将尝试使用当前cherrypy.serving.request.app
找到一个页面处理程序,该页面处理程序设置为清空app,因为CherryPy树中没有任何内容与/foo
路径相对应。所以它什么都找不到。
这里你需要的是替换前缀以更改当前的应用程序。也就是说将that line改为此。
cherrypy.serving.request.app = cherrypy.tree.apps[prefix]
但由于cherrypy.dispatch.VirtualHost
非常小,您可以轻松地重写代码。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cherrypy
from cherrypy._cpdispatch import Dispatcher
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 80,
'server.thread_pool' : 8
},
'hostmap' : {
'api.domain.com' : '/app1',
'www.domain.com' : '/app2'
}
}
appConfig1 = {
'/' : {
'tools.json_out.on' : True
}
}
appConfig2 = {
'/' : {
'tools.encode.encoding' : 'utf-8'
}
}
def VirtualHost(nextDispatcher = Dispatcher(), useXForwardedHost = True, **domains):
def dispatch(pathInfo):
request = cherrypy.serving.request
domain = request.headers.get('Host', '')
if useXForwardedHost:
domain = request.headers.get('X-Forwarded-Host', domain)
prefix = domains.get(domain, '')
if prefix:
request.app = cherrypy.tree.apps[prefix]
result = nextDispatcher(pathInfo)
# Touch up staticdir config. See
# https://bitbucket.org/cherrypy/cherrypy/issue/614.
section = request.config.get('tools.staticdir.section')
if section:
section = section[len(prefix):]
request.config['tools.staticdir.section'] = section
return result
return dispatch
class App1:
@cherrypy.expose
def index(self):
return {'bar': 42}
class App2:
@cherrypy.expose
def index(self):
return '<em>foo</em>'
if __name__ == '__main__':
config['/'] = {'request.dispatch': VirtualHost(**config['hostmap'])}
cherrypy.tree.mount(App1(), '/app1', appConfig1)
cherrypy.tree.mount(App2(), '/app2', appConfig2)
cherrypy.quickstart(config = config)