覆盖Twisted.web中的所有默认资源/响应

1 投票
1 回答
1082 浏览
提问于 2025-04-16 07:47

这是一个关于如何设置一个非常基础的HTTP前端的问题。

我想确保在没有我明确指示的情况下,绝对不会返回任何HTML内容。

我有一个/zoo的链接。对于任何错误信息或者“没有这个资源”的回应,我希望直接断开连接或者返回一个空的回应。

我觉得这个问题很简单,但就是想不明白怎么做 :)

我知道我可以通过不使用特定的子路径来实现,但我想要更高效的做法,想尽早处理这些情况……也许不使用资源?

class HttpApi(resource.Resource):
    isLeaf = True
    def render_POST(self, request):
        return "post..."


application = service.Application("serv")

json_api = resource.Resource()
json_api.putChild("zoo", HttpApi())
web_site = server.Site(json_api)
internet.TCPServer(8001, web_site).setServiceParent(application)

1 个回答

2

先来了解一些基础知识

twisted.web 的工作原理是这样的:

有一个叫做 Site 的类,它是一个 HTTP 工厂。每当有请求进来时,都会调用这个类。实际上,会有一个叫做 getResourceFor 的函数被调用,以获取适合处理这个请求的资源。这个 Site 类是用根资源初始化的。然后,Site.getResourceFor 函数会在根资源上调用 resource.getChildForRequest

调用流程是:

Site.getResourceFor -> resource.getChildForRequest (根资源)

现在我们来看看 getChildForRequest:

def getChildForRequest(resource, request):
    """
    Traverse resource tree to find who will handle the request.
    """
    while request.postpath and not resource.isLeaf:
        pathElement = request.postpath.pop(0)
        request.prepath.append(pathElement)
        resource = resource.getChildWithDefault(pathElement, request)
    return resource

发生的事情是,当资源通过 putChild(path) 注册时,它们就成为了那个资源的子资源。举个例子:

root_resource
|
|------------ resource r1 (path = 'help')
|----resource r2 (path = 'login')  |
|                                  |----- resource r3 (path = 'registeration')
|                                  |----- resource r4 (path = 'deregistration')

一些反思:

  1. 现在 r1 会处理路径为 http://../help/ 的请求
  2. 现在 r3 会处理路径为 http://../help/registration/ 的请求
  3. 现在 r4 会处理路径为 http://../help/deregistration/ 的请求

但是:

  1. r3 会处理路径为 http://../help/registration/xxx/ 的请求
  2. r3 会处理路径为 http://../help/registration/yyy/ 的请求

关于解决方案:

你需要创建一个 Site 的子类来:

  1. 检查路径是否与返回的资源完全匹配,只有在 pathElement 为空时才处理它,或者
  2. 返回一个资源,这个资源将作为你的处理器来处理其他方面的请求

你需要创建自己的资源

def render(self, request):
    request.setResponseCode(...)
    return ""

撰写回答