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.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 ответа

Решение

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

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

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

Другие вопросы по тегам