如何读取由WSGI的 start_response设置的响应头
在找一种方法来读取WSGI start_response 对象设置了哪些头信息。我们知道头信息被存储在某处,因为它们在返回语句之后才会被传输,但它们存储在哪里,以及如何访问它们?
示例代码:
from wsgiref.simple_server import make_server
from wsgiref.headers import Headers
def hello_world_app(environ, start_response):
status = "200 OK" # HTTP Status
headers = [("Content-type", "text/plain; charset=utf-8")] # HTTP Headers
start_response(status, headers)
print("???") # <- read response header here that has been set by start_response
return [b"Hello workld"]
environ.items()]
with make_server("", 8000, hello_world_app) as httpd:
print("Serving on port 8000...")
httpd.serve_forever()
解决方案
你的应用程序函数 hello_world_app 正在被 BaseHandler 调用,具体在此处 在此处:
self.result = application(self.environ, self.start_response)
头信息也被存储在那里,正如你在基类处理程序的此处看到的:在此处:
self.headers = self.headers_class(headers)
于是问题就变成:如何在应用程序函数内部访问基类处理程序的实例?self.environ 只是一个普通字典,因此不可访问,但 self.start_response 是一个绑定方法——例如 如何在Python中找到绑定方法的实例? 你可以通过 __self__ 访问它绑定的实例,示例如下:
print(start_response.__self__.headers)
其输出为:
Content-type: text/plain; charset=utf-8
这归因于 Headers.__str__ 的实现。
如果你想用 Python类型注解 来做这件事,请注意:
StartResponsetype 只是一个Callable,不是MethodType,因此它不定义一个__self__属性1;并且BaseHandler不定义一个headers属性(实际接收到的wsgiref.simple_server.ServerHandler也没有)。
因此最好只是禁用对该行的静态检查:
from collections.abc import Iterable
from typing import Any
from wsgiref.simple_server import make_server
from wsgiref.types import StartResponse
def hello_world_app(
environ: dict[str, Any], start_response: StartResponse
) -> Iterable[bytes]:
start_response("200 OK", [("Content-type", "text/plain; charset=utf-8")])
print(start_response.__self__.headers) # type: ignore
return [b"Hello world"]
with make_server("", 8000, hello_world_app) as httpd:
print("Serving on port 8000...")
httpd.serve_forever()
这将让例如 mypy 等工具满意。
1 这一定义也正确——起始响应可调用对象 是Web服务器网关接口的一个通用部分,不要求必然是绑定方法,通常也不能依赖于它就是一个绑定方法。只有在使用此参考实现的具体情形下,我们知道它在运行时会是一个绑定方法,除非未来实现有变。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。