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

So, while ago I asked similar question: How to get whole request POST body in Python (Flask)

And I got an answer that actually flask.request.data is the raw POST BODY. But that seems to work only if the request has few additional headers:

headers = {
    'Content-type': 'binary/octet-stream',
    'Content-length': len(postBody),
    'Content-transfer-encoding': 'binary',
}

If those headers are not present, the flask.request.data will be empty:

from flask import Flask

app = Flask(__name__)
@app.route('/', methods=['POST'])
def parse_request():
    data = flask.request.data # but data will be empty unless the request has the proper content-type header...

So now I found the request is actually application/x-www-form-urlencoded (which is default mimetype) then I could take the data like this:

app = Flask(__name__)
@app.route('/', methods=['POST'])
def parse_request():
    data = flask.request.data # but data will be empty unless the request has the proper content-type header...
    if not data:
        data = request.form.keys()[0]

But I’m not sure that I could count on it…

So, is there a way to be able to obtain the raw post body of any post request, regardless of the headers?

Get raw data from POST request in Flask

How can I get the raw data from a POST request in Flask? I am moving from web.py to Flask and have some clients in production that unfortunately are using the content-type header application/x-www-for

How can I get the whole request POST body in Python with Flask?

I want to be able to get the whole POST body of the request as a string or file handle that I can read but I’m unable to find a way (I’m new to Flask and Python for web at all). This is what I got: fr

Sending a file as a raw data in a http POST body using python without multipart encode header

Is there a way using python to send the raw file data in the post body without multipart encoding cause this is the requirements of the API I can post here a snippet in delphi that do it but I need it

Python POST request – set whole raw post body?

I want to send a POST request with Python, setting the whole POST body to be a certain string lets say. How would I do that? urlib/urlib2/httplib, doesn’t matter to me… Thank you.

Get raw query string in flask

Is there a way to get the raw query string or a list of query string parameters in Flask? I know how to get query string parameters with request.args.get(‘key’), but I would like to be able to take in

TypeError Ajax Post – Flask Python

Just starting out with Flask and Python. I have a simple form that does an ajax post using the jQuery ajax form library. It goes to a function on the python side and add’s a user to a mongoDb database

Get raw post data

According to php manual nor php://input neither $HTTP_RAW_POST_DATA work with multipart/form-data POST-requests. php://input allows you to read raw POST data. It is a less memory intensive alternativ

Get raw post data

According to php manual nor php://input neither $HTTP_RAW_POST_DATA work with multipart/form-data POST-requests. php://input allows you to read raw POST data. It is a less memory intensive alternativ

Python: BaseHTTPRequestHandler – Read raw post

How do I read the raw http post STRING. I’ve found several solutions for reading a parsed version of the post, however the project I’m working on submits a raw xml payload without a header. So I am tr

Flask – python header import is not working

Server – Flask + Python 2.6.2 + CentOS Dashboard @app.route(‘/admin/dashboard’) def admin_dashboard(): return render_template(‘admin/dashboard.html’) I tried to load dashboard.html with header.thml d

Answers

There’s request.stream when the mime type is not recognized.

data = request.stream.read()

I just had this issue, and I think a few of you might be able to benefit from my solution. I created a WSGI middleware class that saves the raw POST body from the socket. I saved the value in the WSGI variable ‘environ’ so I could refer to it as request.environ[‘body_copy’] within my Flask app.

You need to be careful that the post data is not too large, or you might have memory issues on your server.

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

    def __call__(self, environ, start_response):

        from cStringIO import StringIO
        length = environ.get('CONTENT_LENGTH', '0')
        length = 0 if length == '' else int(length)

        body = environ['wsgi.input'].read(length)
        environ['body_copy'] = body
        environ['wsgi.input'] = StringIO(body)

        # Call the wrapped application
        app_iter = self.application(environ, 
                                    self._sr_callback(start_response))

        # Return modified response
        return app_iter

    def _sr_callback(self, start_response):
        def callback(status, headers, exc_info=None):

            # Call upstream start_response
            start_response(status, headers, exc_info)
        return callback

app.wsgi_app = WSGICopyBody(app.wsgi_app)

request.environ['body_copy'] # This is the raw post body you can use in your flask app

I’m using Flask 0.10.1, and if you look at the source code, it turns out that you can call

request.get_data()

To get the raw data, regardless of content type. The request data is then cached, and you can subsequently access request.data, request.json, request.form at will.

However, if you access request.data first, it will call get_data with different options, where the form parsing runs first, and the actual request data read from the stream is never stored; request.form, request.json etc. then has nothing to work with.

I finally figured out if I do this:

request.environ[‘CONTENT_TYPE’] = ‘application/something_Flask_ignores’

Then request.data will actually have the post data. This is if you can’t control the client request and want to just override it on the server.