Python httplib и POST

в настоящее время я работаю с куском кода, который был написан кем-то другим. Он использует 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, возможно). Как я уже сказал, код не мой, и он поставляется в гораздо больших количествах, чем то, что я только что опубликовал выше. Рефакторинг вызовет серьезные проблемы. Меня интересует любые надежные обходные пути.

редактировать

отладочную информацию:

send: 'POST /api/snippet/ HTTP/1.1rnHost: monkeylabs.plrnAccept-Encoding: identityrnContent-Type: application/jsonrnAccept: */*rnUser-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.pre03rnrn[{"id":"route"}]'
reply: 'HTTP/1.0 201 CREATEDrn'
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 ответов


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

conn.set_debuglevel(1)

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


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

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

headers['Content-Length'] = "%d"%(len('[{"id":"route"}]'))

вы проверили документацию 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 -- вы увидите, что используете его неправильно в своем образце. В частности, он автоматически добавляет Примите заголовок по умолчанию.

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