Python: BaseHTTPRequestHandler — прочитать необработанный пост

Как прочитать необработанный http-пост STRING. Я нашел несколько решений для чтения проанализированной версии сообщения, однако проект, над которым я работаю, отправляет необработанную полезную нагрузку xml без заголовка. Итак, я пытаюсь найти способ прочитать данные сообщения без их анализа в массив ключей => значений.


person kwolfe    schedule 26.07.2013    source источник


Ответы (4)


Я думаю, что self.rfile.read(self.headers.getheader('content-length')) должен возвращать необработанные данные в виде строки. Согласно документам непосредственно внутри класса BaseHTTPRequestHandler:

- rfile is a file object open for reading positioned at the
start of the optional input data part;
person smakateer    schedule 26.07.2013
comment
После попытки и быстрого поиска в Google эта операция блокирует выполнение как для меня, так и для других. - person kwolfe; 26.07.2013
comment
Необходимо указать длину содержимого: data = self.rfile.read(int(self.headers.getheader('content-length'))) - person kwolfe; 26.07.2013
comment
Да, прости. Это блокировка, потому что объект rfile является сокетом, и вызов read() в основном говорит «читать, пока не останется ничего для чтения», но есть еще что читать, пока сокет открыт, поэтому он зависает и ждет входящего контента. Серверы избегают зависания, ВСЕГДА указывая СКОЛЬКО контента для чтения. Извините, я должен был поставить это в первую очередь. - person smakateer; 26.07.2013
comment
В Python 3.5 вам нужно использовать get вместо getheader. - person CyberFonic; 03.11.2017
comment
Что происходит, когда отсутствует заголовок длины содержимого? Ваш сервер просто падает? - person Jamie Marshall; 18.09.2018

self.rfile.read(int(self.headers.getheader('Content-Length'))) вернет необработанные данные HTTP POST в виде строки.

Разбивая это:

  1. Заголовок «Content-Length» указывает, сколько байтов содержат данные HTTP POST.
  2. self.headers.getheader('Content-Length') возвращает длину содержимого (значение заголовка) в виде строки.
  3. Это должно быть преобразовано в целое число перед передачей в качестве параметра в self.rfile.read(), поэтому используйте функцию int().

Кроме того, обратите внимание, что имя заголовка чувствительно к регистру, поэтому оно должно указываться только как 'Content-Length'.

Изменить: очевидно, что поле заголовка не чувствительно к регистру (по крайней мере, в Python 2.7.5), что, я считаю, является правильным поведением, поскольку https://tools.ietf.org/html/rfc2616 сообщает:

Каждое поле заголовка состоит из имени, за которым следует двоеточие (":") и значение поля. Имена полей нечувствительны к регистру.

person Sindhuri Kuppasad    schedule 02.01.2014
comment
Пожалуйста, будьте более подробными, я понятия не имею, что вы предлагаете. - person jb.; 02.01.2014
comment
@jb: я добавил в ответ больше деталей. Дайте мне знать, если есть что-то конкретное, что еще нужно уточнить. - person Sindhuri Kuppasad; 02.01.2014
comment
@SindhuriKuppasad, имя заголовка не чувствительно к регистру. Следующие операторы возвращают длину содержимого в моих тестах: self.headers.getheader('content-length') и self.headers.getheader('content-LENGTH') - person famzah; 07.11.2015
comment
@famzah, это интересно. Я не могу вспомнить, какую версию Python я использовал, когда писал этот ответ, но случай имел значение, и именно поэтому я поставил ответ здесь в первую очередь. Проверил сейчас на 2.7.5 и вы правы, регистр значения не имеет. - person Sindhuri Kuppasad; 10.11.2015
comment
В python3 это будет self.headers.get('content-length') - person Amarghosh; 12.04.2018

Для python 3.7 у меня сработало следующее:

rawData = (self.rfile.read(int(self.headers['content-length']))).decode('utf-8')

С помощью других ответов на этот вопрос и этого и это. Последняя ссылка на самом деле содержит полное решение.

person Ashiq    schedule 12.09.2019
comment
Откуда вы знаете, как декодировать в utf-8? - person Jules G.M.; 22.07.2021
comment
@JulesG.M. это то, что я нашел в последней ссылке, которую я дал. Также utf-8 работал с содержимым, которое я читал как необработанные данные со стороны сервера. Если серверная сторона возвращает его закодированным в любом другом формате, это значение также потребуется изменить для декодирования. - person Ashiq; 23.07.2021

Метод read() для объекта io.BufferedIOBase считывается до EOF. Не все браузеры отправляют символ EOF (источник). Чтение байтов Content-Length — хорошее решение. Мне также помогло использование метода read1(). Он считывает как можно больше за один неблокирующий вызов API.

person Alexandre de Verteuil    schedule 02.11.2020