webentwicklung-frage-antwort-db.com.de

Roh werden POST body in Python Flask unabhängig vom Content-Type-Header

Zuvor fragte ich Wie erhalte ich Daten in Flask-Anfrage , weil request.data leer war. In der Antwort wurde erklärt, dass request.data der unformatierte Post-Body ist, aber leer sein wird, wenn Formulardaten analysiert werden. Wie kann ich den rohen Post-Body unbedingt bekommen?

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

Verwenden Sie request.get_data() , um die Rohdaten unabhängig vom Inhaltstyp abzurufen. Die Daten werden zwischengespeichert und Sie können nach Belieben auf request.data, request.json, request.form zugreifen.

Wenn Sie zuerst auf request.data zugreifen, wird get_data mit einem Argument aufgerufen, um zuerst Formulardaten zu parsen. Wenn die Anforderung einen Formularinhaltstyp hat (multipart/form-data, application/x-www-form-urlencoded oder application/x-url-encoded), werden die Rohdaten verbraucht. request.data und request.json erscheinen in diesem Fall leer.

179
miracle2k

Es gibt request.stream, wenn der Mime-Typ nicht erkannt wird.

data = request.stream.read()
26
jd.

Ich hatte gerade dieses Problem, und ich glaube, einige von Ihnen könnten von meiner Lösung profitieren. Ich habe eine WSGI-Middleware-Klasse erstellt, die den rohen POST -Körper aus dem Socket speichert. Ich habe den Wert in der WSGI-Variablen 'environ' gespeichert, damit ich ihn in meiner Flask-App als request.environ ['body_copy'] bezeichnen kann. 

Sie müssen darauf achten, dass die Postdaten nicht zu groß sind oder dass auf Ihrem Server Speicherprobleme auftreten können.

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
14
jhaski

Ich habe endlich herausgefunden, ob ich das mache:

request.environ['CONTENT_TYPE'] = 'application/something_Flask_ignores'

Dann hat request.data tatsächlich die Postdaten. Dies ist der Fall, wenn Sie die Clientanforderung nicht steuern können und sie einfach auf dem Server überschreiben möchten.

4
KevinH

Das funktioniert für mich:

@application.route("/getrawdata", methods=['POST'])
def getrawdata():
    #Your processing logic here
    return request.get_data()

Ich habe dies in Postman erfolgreich getestet, indem ich in Raw Data eine binäre Zeichenfolge übergeben habe. Damit dies funktioniert, müssen Sie das Anforderungspaket in die Flasche importieren:

from flask import request
0
rahul4data