Python在某些DELETE请求中出现BadStatusLine错误
我正在尝试使用python-rest-client(http://code.google.com/p/python-rest-client/wiki/Using_Connection)来测试一些RESTful网络服务。因为我刚开始学习,所以我把测试指向了http://www.predic8.com/rest-demo.htm上提供的示例服务。
我在创建、更新或获取条目(也就是POST和GET请求)时没有问题。但是,当我尝试发送DELETE请求时,它却失败了。我可以使用Firefox的REST客户端成功发送DELETE请求,也可以在其他服务上发送DELETE请求,但我一直搞不明白为什么在这个情况下不行。我使用的是更新后的Python 3和Httplib2,但我也尝试了Python 2.5,以便使用python-rest-client自带的Httplib2版本。在这两种情况下,我都遇到了同样的问题。
代码很简单,和文档中的用法一致:
from restful_lib import Connection
self.base_url = "http://www.thomas-bayer.com"
self.conn = Connection(self.base_url)
response = self.conn.request_delete('/sqlrest/CUSTOMER/85')
我查看了浏览器工具和我代码生成的HTTP请求,但我看不出为什么一个能工作而另一个不行。这是我收到的跟踪信息:
Traceback (most recent call last):
File "/home/fmk/python/rest-client/src/TestExampleService.py", line 68, in test_CRUD
self.Delete()
File "/home/fmk/python/rest-client/src/TestExampleService.py", line 55, in Delete
response = self.conn.request_delete('/sqlrest/CUSTOMER/85')
File "/home/fmk/python/rest-client/src/restful_lib.py", line 64, in request_delete
return self.request(resource, "delete", args, headers=headers)
File "/home/fmk/python/rest-client/src/restful_lib.py", line 138, in request
resp, content = self.h.request("%s://%s%s" % (self.scheme, self.host, '/'.join(request_path)), method.upper(), body=body, headers=headers )
File "/home/fmk/python/rest-client/src/httplib2/__init__.py", line 1175, in request
(response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/home/fmk/python/rest-client/src/httplib2/__init__.py", line 931, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/home/fmk/python/rest-client/src/httplib2/__init__.py", line 897, in _conn_request
response = conn.getresponse()
File "/usr/lib/python3.2/http/client.py", line 1046, in getresponse
response.begin()
File "/usr/lib/python3.2/http/client.py", line 346, in begin
version, status, reason = self._read_status()
File "/usr/lib/python3.2/http/client.py", line 316, in _read_status
raise BadStatusLine(line)
http.client.BadStatusLine: ''
到底哪里出问题了?我该怎么处理?其实,我更希望能得到一些调试的建议。我在脚本中更改了域名,并指向我自己的机器,以便查看请求。我在BurpProxy中查看并修改了Firefox的请求,使其与我的脚本请求匹配。修改后的Burp请求仍然有效,而Python请求却仍然不行。
2 个回答
下面的脚本可以正确地从服务器返回 404
响应:
#!/usr/bin/env python3
import http.client
h = http.client.HTTPConnection('www.thomas-bayer.com', timeout=10)
h.request('DELETE', '/sqlrest/CUSTOMER/85', headers={'Content-Length': 0})
response = h.getresponse()
print(response.status, response.version)
print(response.info())
print(response.read()[:77])
python -V
=> 3.2
curl -X DELETE http://www.thomas-bayer.com/sqlrest/CUSTOMER/85
curl: (52) Empty reply from server
状态行是必须的; HTTP 服务器必须返回它。或者至少要发送 411 需要长度 的响应。
curl -H 'Content-length: 0' -X DELETE \
http://www.thomas-bayer.com/sqlrest/CUSTOMER/85
正确返回 404
。
看起来问题在于服务器希望DELETE请求中有一些消息内容。对于DELETE请求来说,这种期望有点不寻常,但通过在请求头中指定Content-Length:0,我成功地进行了DELETE操作。
在某个环节(可能是在python-rest-client或httplib2中),如果我尝试这样做:
from restful_lib import Connection
self.base_url = "http://www.thomas-bayer.com"
self.conn = Connection(self.base_url)
response = self.conn.request_delete('/sqlrest/CUSTOMER/85', headers={'Content-Length':'0'})
为了验证这个概念,我查看了请求发生时的堆栈跟踪:
File "/home/fmk/python/rest-client/src/httplib2/__init__.py", line 897, in _conn_request
response = conn.getresponse()
我在那时打印了headers参数,确认内容长度没有出现,然后我在请求之前添加了:
if(method == 'DELETE'):
headers['Content-Length'] = '0'
我认为真正的问题在于这个服务有点问题,但至少我对httplib2有了更深入的了解。我看到其他一些困惑的人在寻找关于REST和Python的帮助,所以希望我不是唯一一个从中受益的人。