Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python WSGI: Reading env['wsgi.input'] more than once

I am building a simple web service that requires all requests to be signed. The signature hash is generated using request data including the request body. My desire is to have a middleware component that validates the request signature, responding with an error if the signature is invalid. The problem is the middleware needs to read the request body using env['wsgi.input'].read(). This advances the pointer for the request body string to the end, which makes the data inaccessible to other components further down in the chain of execution.

Is there any way to make it so env['wsgi.input'] can be read twice?

Ex:

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)
like image 403
rr. Avatar asked Oct 11 '22 23:10

rr.


2 Answers

You can try seeking back to the beginning, but you may find that you'll have to replace it with a StringIO containing what you just read out.

like image 155
Ignacio Vazquez-Abrams Avatar answered Oct 13 '22 12:10

Ignacio Vazquez-Abrams


The following specification deals with that exact problem, providing explanation of the problem as well as the solution including source code and special cases to take into account: http://wsgi.readthedocs.org/en/latest/specifications/handling_post_forms.html

like image 32
zvone Avatar answered Oct 13 '22 13:10

zvone