某些DELETE请求的Python BadStatusLine错误
我正在尝试使用python-rest-client(http://code.google.com/p/python-rest-client/wiki/Using_Connection)来执行某些RESTful web服务的测试。由于我只是在学习,所以我一直在用http://www.predic8.com/rest-demo.htm提供的示例服务指向我的测试。某些DELETE请求的Python BadStatusLine错误
我在创建条目,更新条目或检索条目(POST和GET请求)方面没有问题。当我尝试进行DELETE请求时,它失败。我可以使用Firefox REST客户端执行DELETE请求,并且它们可以工作。我也可以在其他服务上做DELETE请求,但是我一直在疯狂地试图弄清楚为什么它在这种情况下不起作用。我正在使用更新的Httplib2的Python 3,但我也尝试过Python 2.5,以便可以使用包含Httplib2的版本的python-rest-client。无论哪种情况,我都会遇到同样的问题。
代码很简单,匹配记录的使用:
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请求仍然没有。
下面的脚本正确产生从服务器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
Status-Line is not optional; HTTP服务器必须返回它。或至少发送411 Length Required回应。
curl -H 'Content-length: 0' -X DELETE \
http://www.thomas-bayer.com/sqlrest/CUSTOMER/85
正确返回404
。
显然问题在于服务器期望DELETE请求有一些消息正文。对DELETE来说这是一个不寻常的期望,但通过在头文件中指定Content-Length:0,我能够成功执行DELETE。
沿途某处(在python-休息客户端或httplib2的),在Content-Length头被打掉了,如果我尝试做:
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()
我打印头参数存在,以确认内容长度是不存在,那么我加入:
if(method == 'DELETE'):
headers['Content-Length'] = '0'
之前的请求。
我认为真正的答案是服务不可靠,但至少我已经了解了httplib2。我看到一些其他困惑的人在寻找REST和Python的帮助,所以希望我不是唯一能从中获得一些东西的人。
你是对的:'curl -H'Content-length:0'-X DELETE http:// www.thomas-bayer.com/sqlrest/CUSTOMER/85'返回非空响应。 – jfs
Firefox未收到空的答复。假设客户条目存在于进行DELETE请求时,我得到一个包含以下内容的200 OK响应: 此外,这不是简单地认为的Python请求上处理的响应失败。该项目被Firefox请求成功删除(后续GET请求接收404响应),但该记录在Python DELETE尝试后仍然存在。 –
@Mikey 0:服务器上可能有一些抗措施。它可能会检查用户代理,引用者,cookie等。 – jfs
如上所述,我已经使用拦截代理修改了Firefox请求标头,以使它们与我的脚本制作的请求相匹配。代理请求仍然可以在没有Cookie,用户代理,引用者的情况下运行。一个头似乎正在提出,我认为这可能是我的问题是内容长度。即使我在Burp中删除它,它仍会将其添加回来。另一方面,我试图在我的python-rest-client DELETE调用中将Content-Length:0作为参数传递,但我仍然没有看到它来自我的Python脚本的请求。我认为服务器不知道我的请求结束了吗? –