如何从原始HTTP请求字节流构造webob.Request或WSGI 'environ'字典?

3 投票
1 回答
1907 浏览
提问于 2025-04-15 12:19

假设我有一个字节流,里面包含以下内容:

POST /mum/ble?q=huh
Content-Length: 18
Content-Type: application/json; charset="utf-8"
Host: localhost:80

["do", "re", "mi"]

有没有办法从中生成一个WSGI风格的'environ'字典呢?

希望我能找到一个简单的答案,做到这一点和反向操作一样简单。

考虑一下:

>>> import json
>>> from webob import Request
>>> r = Request.blank('/mum/ble?q=huh')
>>> r.method = 'POST'
>>> r.content_type = 'application/json'
>>> r.charset = 'utf-8'
>>> r.body = json.dumps(['do', 're', 'mi'])
>>> print str(r) # Request's __str__ method gives raw HTTP bytes back!
POST /mum/ble?q=huh
Content-Length: 18
Content-Type: application/json; charset="utf-8"
Host: localhost:80

["do", "re", "mi"]

1 个回答

5

重复使用Python标准库的代码有点棘手,因为它并不是为了这样重复使用而设计的,但其实是可以做到的,比如:

import cStringIO
from wsgiref import simple_server, util

input_string = """POST /mum/ble?q=huh HTTP/1.0
Content-Length: 18
Content-Type: application/json; charset="utf-8"
Host: localhost:80

["do", "re", "mi"]
"""

class FakeHandler(simple_server.WSGIRequestHandler):
    def __init__(self, rfile):
        self.rfile = rfile
        self.wfile = cStringIO.StringIO() # for error msgs
        self.server = self
        self.base_environ = {}
        self.client_address = ['?', 80]
        self.raw_requestline = self.rfile.readline()
        self.parse_request()

    def getenv(self):
        env = self.get_environ()
        util.setup_testing_defaults(env)
        env['wsgi.input'] = self.rfile
        return env

handler = FakeHandler(rfile=cStringIO.StringIO(input_string))
wsgi_env = handler.getenv()

print wsgi_env

基本上,我们需要创建一个新的请求处理器类,以假装服务器正常进行的构建过程(比如从客户端的套接字生成的rfilewfile等等)。我觉得这还不算完整,但应该差不多,希望能对你有帮助!

另外,我还修正了你示例中的HTTP请求:如果在原始请求行的末尾没有HTTP/1.0HTTP/1.1,那么POST请求就会被认为格式不正确,这样会导致异常,并在handler.wfile上出现错误信息。

撰写回答