本文介绍了如何单独使用CherryPy来服务多个域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'd like to use a standalone instance of CherryPy to serve several domains from a single server. I'd like each domain to be served from a completely separate CherryPy application, each with its own configuration file.

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

I played with cherrypy.dispatch.VirtualHost, but it seems like separate configuration files aren't possible.

类似的问题(此处)表明,困难,但没有解释为什么而且可能是由于没有人回答这个问题.

A similar question (here) suggests that this is quite difficult, but doesn't explain why and might have been due to the fact that no one answered the question.

CherryPy配方可用于多个apps 显示了如何使用单独的配置文件加载多个沙盒应用程序,但看起来它们是在同一域中提供的.

This CherryPy recipe for multiple apps shows how to load multiple sandboxed apps with separate configuration files, but it looks like they are being served form the same domain.

我可以理解答案可能是将CherryPy用作Nginx或Apache之后的WSGI服务器",但我宁愿只在该特定服务器上处理CherryPy.

I can understand that the answer might be, "use CherryPy as a WSGI server behind Nginx or Apache," but I'd rather only deal with CherryPy on this particular server.

推荐答案

在同一仓库中,有虚拟主机食谱.但是,它使用共享的应用程序.我看不到让 cherrypy.dispatch.VirtualHost 与单独安装的应用程序一起工作的方法.这是因为 cherrypy.serving.request.app 是在调用调度程序之前设置的.假设您具有以下条件.

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)

所有 cherrypy.dispatch.VirtualHost 所做的工作都是在当前网址之前添加域前缀,例如请求 http://www.domain.com/foo 会导致/app2/foo/作为内部路径发送到下一个通常为的调度程序cherrypy.dispatch.Dispatcher .但是,后者将尝试使用当前 cherrypy.serving.request.app 来查找页面处理程序,该页面处理程序设置为空应用程序,因为CherryPy树中没有任何内容与/foo 相关小路.因此它将一无所获.

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]

但是,由于 cherrypy.dispatch.VirtualHost 非常小,因此您可以轻松地在代码中重写.

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)

这篇关于如何单独使用CherryPy来服务多个域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 19:00