Отримайте неочищене тіло POST в Python Flask незалежно від заголовка Content Content


131

Раніше я запитував, як отримати дані, отримані у 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

Відповіді:


218

Використовуйте 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в цьому випадку буде видано порожнім.


2
Це, здається, порушується
dequis

34

request.streamце потік необроблених даних, що передається програмі сервером WSGI. Під час читання не виконується розбір, хоча зазвичай ви хочете request.get_data()замість цього.

data = request.stream.read()

Потік буде порожнім, якщо він раніше був прочитаний за request.dataіншим атрибутом.


15

Я створив проміжне програмне забезпечення WSGI, яке зберігає сировину з environ['wsgi.input']потоку. Я зберег значення в середовищі WSGI, щоб я міг отримати доступ до нього з request.environ['body_copy']мого додатка.

Це не обов'язково в Werkzeug або Flask, оскільки request.get_data()вони отримують необроблені дані незалежно від типу вмісту, але з кращим поводженням з HTTP та WSGI поведінкою.

Це читає все тіло в пам'ять, що буде проблемою, якщо, наприклад, розміщено великий файл. Це нічого не прочитає, якщо Content-Lengthзаголовок відсутній, тому він не обробляє потокові запити.

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']

6

request.dataбуде порожнім, якщо request.headers["Content-Type"]його розпізнають як дані форми, на які буде проаналізовано request.form. Щоб отримати необроблені дані незалежно від типу вмісту, використовуйте request.get_data().

request.dataвиклики request.get_data(parse_form_data=True), що призводить до різної поведінки для даних форми.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.