【问题标题】:How can CherryPy alone be used to serve multiple domains?如何单独使用 CherryPy 服务多个域?
【发布时间】:2013-08-25 04:20:44
【问题描述】:

我想使用 CherryPy 的独立实例从单个服务器为多个域提供服务。我希望每个域都由一个完全独立的 CherryPy 应用程序提供服务,每个应用程序都有自己的配置文件。

我玩过cherrypy.dispatch.VirtualHost,但似乎无法使用单独的配置文件。

一个类似的问题 (here) 表明这很困难,但没有解释原因,可能是因为没有人回答这个问题。

这个CherryPy recipe for multiple apps 展示了如何使用单独的配置文件加载多个沙盒应用程序,但看起来它们是从同一个域提供的。

我可以理解答案可能是“使用 CherryPy 作为 Nginx 或 Apache 后面的 WSGI 服务器”,但我宁愿只在这个特定的服务器上处理 CherryPy。

【问题讨论】:

  • 这实际上听起来像是在 CherryPy 作为服务器的范围之外(并且应该 - 像 Apache 或 Nginx 这样的东西更适合这个)。
  • 是的,我认为它也会超出范围,但后来我发现原始帖子中列出的提示表明它可能不是。鉴于此线程上没有任何活动,我想我会在 CherryPy 前面使用 Nginx。

标签: python cherrypy


【解决方案1】:

在同一个 repo 中,有 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 所做的只是将域前缀添加到当前 url,例如请求http://www.domain.com/foo 将导致/app2/foo/ 作为内部路径发送到下一个调度程序,通常是cherrypy.dispatch.Dispatcher。然而,后者将尝试使用当前设置为空应用程序的cherrypy.serving.request.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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-26
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多