2011-06-10 87 views
7

我目前正在使用一段已被其他人编写的代码。它使用httplib向服务器发送请求。它提供了正确格式的所有数据 - 例如邮件正文,标题值等。Python httplib和POST

问题是,每次尝试发送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的”额外的参数已经在被省略经常使用图书馆。傻我。

+2

顺便说一句,如果你认为你会被调试这个东西很多,安装[Wireshark的(http://www.wireshark.org/ )并用它来窥探电线上的实际情况。 – Darien 2011-06-10 23:17:16

+0

谢谢,我在一开始并不信任,但实际上让我找到了解决方案。再次感谢 – julkiewicz 2011-06-11 00:51:37

+0

服务器有:response.set_header('Access-Control-Allow-Origin','*')? – 2012-08-19 23:30:57

回答

5

尝试添加:

conn.set_debuglevel(1) 

你的代码,所以你可以看到什么是真正发生的事情。

0

您是否检查过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标头。

尝试让您的代码更像功能性示例,同时尝试理解您的代码中使用的调用以及在工作示例中使用的调用。

+1

是的,我确实读过API文档,一切都很好。问题是它不好。通过其他各种方式发出的相同请求 - 比如说浏览器或其他库,效果很好。删除“接受”标题不会改变任何内容。你从API中复制的例子只是做了一些完全不同的事情。这不是一个POST,它不会尝试上传邮件正文。 – julkiewicz 2011-06-10 23:45:27

6

putrequest方法不会自动添加内容长度标题,您需要自己动手或使用request方法。

给你的代码添加for以上循环:

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