[python] Get raw POST body in Python Flask regardless of Content-Type header

Previously, I asked How to get data received in Flask request because request.data was empty. The answer explained that request.data is the raw post body, but will be empty if form data is parsed. How can I get the raw post body unconditionally?

@app.route('/', methods=['POST'])
def parse_request():
    data = request.data  # empty in some cases
    # always need raw data here, not parsed form data

This question is related to python flask werkzeug

The answer is


I created a WSGI middleware that stores the raw body from the environ['wsgi.input'] stream. I saved the value in the WSGI environ so I could access it from request.environ['body_copy'] within my app.

This isn't necessary in Werkzeug or Flask, as request.get_data() will get the raw data regardless of content type, but with better handling of HTTP and WSGI behavior.

This reads the entire body into memory, which will be an issue if for example a large file is posted. This won't read anything if the Content-Length header is missing, so it won't handle streaming requests.

from io import BytesIO

class WSGICopyBody(object):
    def __init__(self, application):
        self.application = application

    def __call__(self, environ, start_response):
        length = int(environ.get('CONTENT_LENGTH') or 0)
        body = environ['wsgi.input'].read(length)
        environ['body_copy'] = body
        # replace the stream since it was exhausted by read()
        environ['wsgi.input'] = BytesIO(body)
        return self.application(environ, start_response)

app.wsgi_app = WSGICopyBody(app.wsgi_app)
request.environ['body_copy']

request.stream is the stream of raw data passed to the application by the WSGI server. No parsing is done when reading it, although you usually want request.get_data() instead.

data = request.stream.read()

The stream will be empty if it was previously read by request.data or another attribute.


request.data will be empty if request.headers["Content-Type"] is recognized as form data, which will be parsed into request.form. To get the raw data regardless of content type, use request.get_data().

request.data calls request.get_data(parse_form_data=True), which results in the different behavior for form data.


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to flask

Flask at first run: Do not use the development server in a production environment Flask - Calling python function on button OnClick event python-How to set global variables in Flask? In Flask, What is request.args and how is it used? How to print from Flask @app.route to python console What does "app.run(host='0.0.0.0') " mean in Flask Making an asynchronous task in Flask Flask ImportError: No Module Named Flask can you add HTTPS functionality to a python flask web server? How to get http headers in flask?

Examples related to werkzeug

Get raw POST body in Python Flask regardless of Content-Type header Get the data received in a Flask request Configure Flask dev server to be visible across the network Get IP address of visitors using Flask for Python 104, 'Connection reset by peer' socket error, or When does closing a socket result in a RST rather than FIN?