Получить необработанное тело POST в Python Flask независимо от заголовка Content-Type

Ранее я спрашивал, как получить данные, полученные в запросе Flask, потому что request.data был пуст. Ответ объяснил, что request.data это необработанное тело сообщения, но оно будет пустым, если данные формы будут проанализированы. Как я могу получить необработанное тело сообщения безоговорочно?

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

4 ответа

Решение

Использование request.get_data() получить необработанные данные независимо от типа контента. Данные кэшируются, и вы можете впоследствии получить доступ request.data, request.json, request.form по желанию.

Если вы получаете доступ request.data во-первых, это вызовет get_data с аргументом для анализа данных формы в первую очередь. Если запрос имеет тип содержимого формы (multipart/form-data, application/x-www-form-urlencoded, или же application/x-url-encoded) тогда исходные данные будут использованы. request.data а также request.json будет казаться пустым в этом случае.

Там в request.stream когда тип пантомимы не распознается.

data = request.stream.read()

У меня только что была эта проблема, и я думаю, что некоторые из вас могли бы извлечь выгоду из моего решения. Я создал класс промежуточного программного обеспечения WSGI, который сохраняет исходное тело POST из сокета. Я сохранил значение в переменной WSGI 'environment', чтобы в приложении Flask я мог ссылаться на него как на request.environ['body_copy'].

Вы должны быть осторожны, чтобы данные не были слишком большими, иначе у вас могут быть проблемы с памятью на вашем сервере.

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

Я наконец понял, если я сделаю это:

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

затем request.data на самом деле будет иметь почтовые данные. Это если вы не можете контролировать запрос клиента и хотите просто переопределить его на сервере.

Это работает для меня:

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

Я успешно проверил это в Postman, передав двоичную строку в Raw Data. Чтобы это работало, вам необходимо импортировать пакет запроса в колбу:

from flask import request
Другие вопросы по тегам