Python httplib и POST - PullRequest
       48

Python httplib и POST

7 голосов
/ 11 июня 2011

В настоящее время я работаю с фрагментом кода, который был написан кем-то другим. Он использует httplib для отправки запросов на сервер. Содержит все данные в правильном формате - например, тело сообщения, значения заголовка и т. Д.

Проблема в том, что каждый раз, когда он пытается отправить запросы POST, данные там есть - я вижу их на стороне клиента, однако на сервер ничего не поступает. Я прочитал спецификацию библиотеки, и ее использование кажется правильным.

Извлеченные библиотечные вызовы выполняются следующим образом:

import httplib

conn = httplib.HTTPConnection('monkeylabs.pl', 80)
conn.connect()
request = conn.putrequest('POST', '/api/snippet/')
headers = {}
headers['Content-Type'] = 'application/json'
headers['User-Agent'] = 'Envjs/1.618 (SpyderMonkey; U; Linux x86_64 2.6.38-10-generic;  pl_PL.utf8; rv:2.7.1) Resig/20070309 PilotFish/1.3.pre03'
headers['Accept'] = '*/*'
for k in headers:
    conn.putheader(k, headers[k])
conn.endheaders()

conn.send('[{"id":"route"}]')

resp = conn.getresponse()
print resp.status
print resp.reason
print resp.read()

conn.close()

Это известная проблема или как? Я использую Python 2.7. Не уверен, как проверить версию httplib.

Пожалуйста, не предлагайте обменять httplib на что-то другое, если только это не очень похоже (возможно, httplib2). Как я уже сказал, код не мой, и он поставляется в гораздо больших объемах, чем то, что я только что опубликовал выше. Рефакторинг это вызовет серьезную проблему. Я заинтересован в любых надежных обходных путях.

EDIT

Вывод отладки:

send: 'POST /api/snippet/ HTTP/1.1\r\nHost: monkeylabs.pl\r\nAccept-Encoding: identity\r\nContent-Type: application/json\r\nAccept: */*\r\nUser-Agent: Envjs/1.618 (SpyderMonkey; U; Linux x86_64 2.6.38-10-generic; pl_PL.utf8; rv:2.7.1) Resig/20070309 PilotFish/1.3.pre03\r\n\r\n[{"id":"route"}]'
reply: 'HTTP/1.0 201 CREATED\r\n'
header: Date: Fri, 10 Jun 2011 23:54:00 GMT
header: Server: WSGIServer/0.1 Python/2.7.1+
header: Vary: Cookie
header: Content-Type: application/json
header: Content-Length: 0
201
CREATED

Обратите внимание, что информация после ответа на самом деле говорит об ответе сервера, а не о самом запросе, который в данном случае пуст. Основная причина заключается в том, что тело запроса само по себе пусто, и я могу наблюдать, получая журнал:

[11/Jun/2011 01:54:00] "POST /api/snippet/ HTTP/1.1" 201 0

И эти три строки:

``
<QueryDict: {}>
<QueryDict: {}>

из:

print '`%s`' % request.raw_post_data
print request.GET
print request.POST

на сервере Django. Похоже, он пытается отправить тело, но не отправляет его в конце.

EDIT (2)

Хорошо, я взял дамп, и он действительно сказал мне, что в сообщении, отправленном из браузера, есть дополнительный параметр, называемый «Content-Length», который был опущен при регулярном использовании библиотеки. Глупый я.

Ответы [ 3 ]

6 голосов
/ 02 марта 2012

Метод putrequest автоматически не добавляет заголовок длины содержимого, вам нужно сделать это самостоятельно или использовать метод request.

Добавьте это в свой код над циклом for:

headers['Content-Length'] = "%d"%(len('[{"id":"route"}]'))
5 голосов
/ 11 июня 2011

попробуйте добавить:

conn.set_debuglevel(1)

в ваш код, чтобы вы могли видеть, что на самом деле происходит.

0 голосов
/ 11 июня 2011

Вы проверили документацию httplib? httplib - это стандартная библиотека Python, и Python также очень хорош при наличии онлайн-документации: http://docs.python.org/library/httplib.html

Пример с этой страницы:

>>> import httplib, urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> headers = {"Content-type": "application/x-www-form-urlencoded",
...            "Accept": "text/plain"}
>>> conn = httplib.HTTPConnection("musi-cal.mojam.com:80")
>>> conn.request("POST", "/cgi-bin/query", params, headers)
>>> response = conn.getresponse()
>>> print response.status, response.reason
200 OK
>>> data = response.read()
>>> conn.close()

Ваш пример выглядит более трудоемким, чем этот, и если вы прочитаете документацию API - например, для putrequest - вы увидите, что вы неправильно используете ее в своем примере. В частности, он автоматически добавляет заголовок Accept по умолчанию.

Попробуйте сделать ваш код более похожим на функциональный пример, а также попытайтесь понять вызовы, используемые как в вашем коде, так и используемые в рабочем примере.

...