web-dev-qa-db-fra.com

Obtenir brut POST corps dans un flacon Python indépendamment de l'en-tête Content-Type

Auparavant, je demandais Comment obtenir les données reçues dans la demande Flask parce que request.data était vide. La réponse a expliqué que request.data est le corps de publication brut, mais sera vide si les données du formulaire sont analysées. Comment puis-je obtenir le post corps brut sans condition?

@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

Utilisez request.get_data() pour obtenir les données brutes, quel que soit le type de contenu. Les données sont mises en cache et vous pouvez ensuite accéder à request.data, request.json, request.form à volonté.

Si vous accédez d'abord à request.data, il appellera get_data avec un argument pour analyser les données de formulaire en premier. Si la demande a un type de contenu de formulaire (multipart/form-data, application/x-www-form-urlencoded ou application/x-url-encoded), les données brutes seront consommées. request.data et request.json apparaîtront vides dans ce cas.

179
miracle2k

Il y a request.stream lorsque le type MIME n'est pas reconnu.

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

Je viens d'avoir ce problème, et je pense que quelques-uns d'entre vous pourraient bénéficier de ma solution. J'ai créé une classe de middleware WSGI qui enregistre le corps brut POST du socket. J'ai enregistré la valeur dans la variable WSGI «environ» afin de pouvoir y faire référence sous le nom de request.environ ['body_copy'] dans mon application Flask. 

Veillez à ce que les données de publication ne soient pas trop volumineuses, sinon vous pourriez avoir des problèmes de mémoire sur votre serveur.

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

J'ai finalement compris si je fais ça:

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

Alors request.data aura réellement les données de publication. Cela se produit si vous ne pouvez pas contrôler la demande du client et souhaitez simplement la remplacer sur le serveur.

4
KevinH

Cela fonctionne pour moi:

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

J'ai testé cela avec succès dans Postman en passant une chaîne binaire dans Raw Data. Pour que cela fonctionne, vous devez importer le package de demande dans la fiole:

from flask import request
0
rahul4data