How Can CherryPy Alone Be Used To Serve Multiple Domains?
Solution 1:
In the same repo, there's vhost recipe. However it uses a shared app. I don't see the way to get cherrypy.dispatch.VirtualHost
working with separately mounted apps. This is because cherrypy.serving.request.app
is set before invocation of the dispatcher. Say you have the following.
hostmap = {
'api.domain.com' : '/app1',
'www.domain.com' : '/app2'
}
cherrypy.tree.mount(App1(), '/app1', appConfig1)
cherrypy.tree.mount(App2(), '/app2', appConfig2)
All what cherrypy.dispatch.VirtualHost
does is prepending domain prefix to current url, e.g. requesting http://www.domain.com/foo
will result in /app2/foo/
as internal path that is sent to a next dispatcher which is usually cherrypy.dispatch.Dispatcher
. However the latter will try to find a page handler using current cherrypy.serving.request.app
which is set to empty app because there's nothing in CherryPy tree that corresonded to /foo
path. So it will find nothing.
All you need here is to replace prefixing to changing the current app. That is to say changing that line to this.
cherrypy.serving.request.app = cherrypy.tree.apps[prefix]
But because cherrypy.dispatch.VirtualHost
is pretty small, you can rewrite in your code easily.
#!/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)
Post a Comment for "How Can CherryPy Alone Be Used To Serve Multiple Domains?"