如何在 Twisted Web 服务器中定义具有多个段的路径

How to define paths with multiple segments in Twisted web server

在类似于 this example 代码的 Twisted 网络服务器中

from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints
from twisted.web.static import File

root = Resource()
root.putChild(b"foo", File("/tmp"))
root.putChild(b"bar", File("/lost+found"))
root.putChild(b"baz", File("/opt"))

factory = Site(root)
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8880)
endpoint.listen(factory)
reactor.run()

如何为多段路径定义响应,而不是上面的示例,其中资源在

处可用
http://example.com/foo 

您希望资源可用,例如,

http://example.com/europe/france/paris

并且,如果它影响答案,以下 URL 将不会提供响应

http://example.com/europe/france
http://example.com/europe
http://example.com

我知道 doco 指的是资源树的使用,但是 only examples given 是单级树,对我的要求来说用处不大。


分辨率

在@jean-paul-calderone 的帮助下,我编写了以下内容,它可以满足我的要求。

对于这个问题,我稍微简化了我的要求,事实上我想输出文件以外的东西,我在下面包含的代码反映了这一点。我很确定我在这里写的不是最好的方法,但它确实提供了我想要的多段 URL,因此可能对有类似需求的其他人有用。

from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints
from twisted.web.resource import NoResource

import html

class ContinentLevelResource(Resource):
    pass

class CountryLevelResource(Resource):
    pass

class CityLevelResource(Resource):
    def render_GET(self, request):
        return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
                b"<title>City Page</title></head><body>"
                b"<p>This is the City page</p></body>")

root = Resource()
continent = ContinentLevelResource()
country = CountryLevelResource()
city = CityLevelResource()
#    
root.putChild(b"europe", continent)
continent.putChild(b"france", country)
country.putChild(b"paris", city)
#
factory = Site(root)
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8880)
endpoint.listen(factory)
reactor.run()

您只需应用与问题中出现的相同 API 用法 - 递归地:

给定:

root = Resource()
tmp = File("/tmp")
root.putChild(b"foo", tmp)
lost_found = File("/lost+found")
root.putChild(b"bar", lost_found)
opt = File("/opt")
root.putChild(b"baz", opt)

您有 /foo/bar/baz. If you wantsome_resourceat/foo/quux` 然后:

tmp.putChild(b"quux", some_resource)

这同样适用于添加额外的级别。因此:

root = Resource()
europe = Resource()
france = Resource()
paris = Resource()

root.putChild(b"europe", europe)
europe.putChild(b"france", france)
france.putChild(b"paris", paris)

在 HTTP 中实际上并没有 "not returning a response" 这样的东西。但是,如果需要,您可以将中间资源 return 设置为 404(未找到)状态。只需将中间 Resource 实例替换为您想要的行为(例如 NotFound 实例)。

您可能还想研究 klein,它实现了基于 "route" 的资源层次结构定义 API,如今这种定义通常更常见(在 Python 中)。