请求内容的校验和(Checksum)

在处理请求时,不同的代码模块可能会读取并预处理请求的数据。 例如,JSON 数据会被读取并处理后存放在 request 对象中, 表单数据也是如此,但它会走另一条处理路径。当你希望对传入的请求数据计算校验和时,这种自动处理就可能变得不方便。 在某些 API 场景中,计算请求数据的校验和是必要的。

幸运的是,通过包装输入流,这件事变得非常简单。

下面的示例展示了如何在数据被读取的同时计算其 SHA1 校验和, 并将其保存到 WSGI 环境中:

import hashlib

class ChecksumCalcStream(object):

    def __init__(self, stream):
        self._stream = stream
        self._hash = hashlib.sha1()

    def read(self, bytes):
        rv = self._stream.read(bytes)
        self._hash.update(rv)
        return rv

    def readline(self, size_hint):
        rv = self._stream.readline(size_hint)
        self._hash.update(rv)
        return rv

def generate_checksum(request):
    env = request.environ
    stream = ChecksumCalcStream(env['wsgi.input'])
    env['wsgi.input'] = stream
    return stream._hash

要使用这个方法,你只需在请求开始读取数据之前插入计算用的输入流。 (例如,要避免在此之前访问 request.form 或类似的内容。 像 before_request_handlers 这样的钩子应当注意不要提前访问请求体)。

示例用法如下:

@app.route('/special-api', methods=['POST'])
def special_api():
    hash = generate_checksum(request)
    # Accessing this parses the input stream
    files = request.files
    # At this point the hash is fully constructed.
    checksum = hash.hexdigest()
    return f"Hash was: {checksum}"