Python WSGI:多次读取env['wsgi.input']

5 投票
2 回答
2271 浏览
提问于 2025-04-16 18:08

我正在构建一个简单的网络服务,所有的请求都需要进行签名。这个签名的哈希值是通过请求的数据生成的,包括请求的主体内容。我希望有一个中间件组件来验证请求的签名,如果签名无效,就返回一个错误。不过问题是,这个中间件需要使用 env['wsgi.input'].read() 来读取请求主体。这会把请求主体的指针移动到最后,这样后面的其他组件就无法再访问这些数据了。

有没有办法让 env['wsgi.input'] 可以被读取两次呢?

例如:

from myapp.lib.helpers import sign_request
from urlparse import parse_qs
import json

class ValidateSignedRequestMiddleware(object):
    def __init__(self, app, secret):
        self._app = app
        self._secret = secret

    def __call__(self, environ, start_response):
        auth_params = environ['HTTP_AUTHORIZATION'].split(',', 1)
        timestamp = auth_params[0].split('=', 1)[1]
        signature = auth_params[1].split('=', 1)[1]

        expected_signature = sign_request(
            environ['REQUEST_METHOD'],
            environ['HTTP_HOST'],
            environ['PATH_INFO'],
            parse_qs(environ['QUERY_STRING']),
            environ['wsgi.input'].read(),
            timestamp,
            self._secret
        )
        if signature != expected_signature:
            start_response('400 Bad Request', [('Content-Type', 'application/json')])
            return [json.dumps({'error': ('Invalid request signature',)})]

        return self._app(environ, start_response)

2 个回答

1

以下的说明文档专门解决了这个问题,里面详细解释了问题的内容以及解决方案,包括源代码和需要注意的特殊情况:http://wsgi.readthedocs.org/en/latest/specifications/handling_post_forms.html

3

你可以尝试回到开始的地方,但你可能会发现需要用一个包含你刚刚读取内容的 StringIO 来替换它。

撰写回答