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: {}>
out of:
print '`%s`' % request.raw_post_data
print request.GET
print request.POST
在 Django 服务器上 来观察。所以看起来它尝试发送正文但最终没有发送。
编辑(2)
好的,我进行了转储,它确实告诉我,在从浏览器发送的消息中,有一个名为“Content-Length”的附加参数,该参数在常规用法中已被省略图书馆。愚蠢的我。
I am currently working with a piece of code that has been written by somebody else. It uses httplib
to make requests to server. It has all the data supplied in a correct format - for example message body, header values, etc.
The problem is that each time it attempts to send a POST requests, the data is there - I can see it on the client side, however nothing arrives to the server. I've read through the library specification and the usage seems to be correct.
The extracted library calls go as follows:
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()
Is this some known issue, or what? I'm using Python 2.7. Not sure how to check the version of httplib.
Please don't suggest to exchange httplib for something else unless it's something really similar (httplib2 perhaps). As I said, the code isn't mine and it comes in much greater amounts than what I've just posted above. Refactoring it would cause a major problem. I'm interested in any reliable workarounds.
EDIT
The debug output:
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
Note that the information after reply actually talks about the server reply, not the request itself, which in this case is empty. The primary cause is that the request body itself is empty which I can observe by getting a log:
[11/Jun/2011 01:54:00] "POST /api/snippet/ HTTP/1.1" 201 0
And those three lines:
``
<QueryDict: {}>
<QueryDict: {}>
out of:
print '`%s`' % request.raw_post_data
print request.GET
print request.POST
on the Django server. So it seems it attempts to send the body but doesn't send it in the end.
EDIT(2)
Ok, I took a dump and it indeed told me that in the message sent from the browser there is an additional parameter called 'Content-Length' which has been omitted in the regular usage of the library. Silly me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
putrequest
方法不会自动添加 Content Length 标头,您需要自己添加或使用request
方法。将其添加到
for
循环上方的代码中:The
putrequest
method does not automatically add the Content Length header, you need to do it yourself or use therequest
method.Add this to your code above the
for
loop:尝试将: 添加
到您的代码中,以便您可以看到实际发生的情况。
try adding:
to your code so you can see what is actually happening.
你检查过 httplib 文档吗? httplib 是一个标准的 Python 库,Python 也非常擅长提供在线文档: http://docs .python.org/library/httplib.html
该页面的示例:
您的示例似乎比这更多工作,如果您阅读 API 文档 - 例如
putrequest
-- 你会发现你在你的应用程序中使用了错误的方法 样本。具体来说,它默认自动添加 Accept 标头。尝试使您的代码更像功能示例,并尝试理解代码中使用的调用以及工作示例中使用的调用。
Have you checked the httplib documentation? httplib is a standard Python library, and Python is also very good about having online documentation: http://docs.python.org/library/httplib.html
The example from that page:
Your example appears to be more work than this, and if you read the API documentation -- for instance for
putrequest
-- you'll see you're using it wrong in your sample. Specifically, it automatically adds the Accept header by default.Try making your code more like the functional example, also try to understand the calls used in both your code and used in the working example.