2011-11-07 59 views
1

我正在尝试使用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请求仍然没有。

回答

1

下面的脚本正确产生从服务器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

+0

Firefox未收到空的答复。假设客户条目存在于进行DELETE请求时,我得到一个包含以下内容的200 OK响应: <?xml version =“1.0”encoding =“UTF-8”?> 此外,这不是简单地认为的Python请求上处理的响应失败。该项目被Firefox请求成功删除(后续GET请求接收404响应),但该记录在Python DELETE尝试后仍然存在。 –

+0

@Mikey 0:服务器上可能有一些抗措施。它可能会检查用户代理,引用者,cookie等。 – jfs

+0

如上所述,我已经使用拦截代理修改了Firefox请求标头,以使它们与我的脚本制作的请求相匹配。代理请求仍然可以在没有Cookie,用户代理,引用者的情况下运行。一个头似乎正在提出,我认为这可能是我的问题是内容长度。即使我在Burp中删除它,它仍会将其添加回来。另一方面,我试图在我的python-rest-client DELETE调用中将Content-Length:0作为参数传递,但我仍然没有看到它来自我的Python脚本的请求。我认为服务器不知道我的请求结束了吗? –

4

显然问题在于服务器期望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的帮助,所以希望我不是唯一能从中获得一些东西的人。

+0

你是对的:'curl -H'Content-length:0'-X DELETE http:// www.thomas-bayer.com/sqlrest/CUSTOMER/85'返回非空响应。 – jfs