How to specify the listening server instances using cherrypy tree.mount?

瘦欲@ 提交于 2021-02-11 15:48:57

问题


Let us create an application server and an admin server. Assume that fusionListener and adminListener contain the application and admin logic we want to expose.

  from cherrypy._cpserver import Server
  fserver = Server()
  fserver.socket_port = 10000
  fserver.subscribe()

  aserver = Server()
  aserver.socket_port = 10001
  aserver.subscribe()

And then to start them:

cherrypy.engine.start()
cherrypy.engine.block()

The tree.mount parameters ask for:

  • the code/ business logic as the first parameter
  • listening url
  • config parameters

Here is how that looks for the above servers:

  cherrypy.tree.mount(fusionListener, r"/fusion.*",fusionConf)
  cherrypy.tree.mount(adminListener, r"/admin.*",adminConf)

But where is the parameter for the server itself - which includes the port being listened to?


回答1:


This is not a well supported case for CherryPy.

The application selection (cherrypy.tree is basically a map of /path -> App) is done before the request dispatch and... long story short, you could use cherrypy.dispatch.VirtualHost and map you sub applications under a main one (that will route depending on the hostname (which the port can be part of). For the listening on multiple ports, can be done, but again this is a very custom arrangement.

I hope this example is illustrative of a possible way to make such feat:

import cherrypy

from cherrypy import dispatch
from cherrypy._cpserver import Server


class AppOne:

    @cherrypy.expose
    def default(self):
        return "DEFAULT from app ONE!"

    @cherrypy.expose
    def foo(self):
        return "FOO from app ONE"


class AppTwo:

    @cherrypy.expose
    def default(self):
        return "DEFAULT from app TWO!"

    @cherrypy.expose
    def foo(self):
        return "FOO from app TWO"


class Root:

    def __init__(self):
        self.one = AppOne()
        self.two = AppTwo()


def bind_two_servers(app_one_port, app_two_port):
    # unsubscribe the default server
    cherrypy.server.unsubscribe()
    s1 = Server()
    s2 = Server()
    s1.socket_port = app_one_port
    s2.socket_port = app_two_port
    # subscribe the server to the `cherrypy.engine` bus events
    s1.subscribe()
    s2.subscribe()


def start_server():
    bind_two_servers(8081, 8082)
    cherrypy.engine.signals.subscribe()
    cherrypy.engine.start()
    cherrypy.engine.block()


config = {
    '/': {
        'request.dispatch': dispatch.VirtualHost(**{
            'localhost:8081': '/one',
            'localhost:8082': '/two',
        })
    }
}

cherrypy.tree.mount(Root(), '/', config)
start_server()

This example will serve AppOne when coming from localhost:8081 and AppTwo when coming from localhost:8082.

The problem is that you can't do multiples cherrypy.tree.mount and expect to route into the different applications using the VirtualHost dispatcher, it assumes that the application resolution is done at that point and is only resolving the path of that application.

Having said all of that... I do not recommend this solution, it can get complicated and it would be better to have some other server in front (like nginx) and serve each path on different processes. This could be an alternative, only if you really really want to avoid any extra server or process in your setup.



来源:https://stackoverflow.com/questions/60838587/how-to-specify-the-listening-server-instances-using-cherrypy-tree-mount

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!