简体   繁体   中英

Python BadStatusLine error on certain DELETE requests

I am trying to use the python-rest-client ( http://code.google.com/p/python-rest-client/wiki/Using_Connection ) to perform testing of some RESTful webservices. Since I'm just learning, I've been pointing my tests at the sample services provided at http://www.predic8.com/rest-demo.htm .

I have no problems with creating entries, updating entries, or retrieving entries (POST and GET requests). When I try make a DELETE request, it fails. I can use the Firefox REST Client to perform DELETE requests and they work. I can also make DELETE requests on other services, but I've been driving myself crazy trying to figure out why it doesn't work in this case. I'm using Python 3 with updated Httplib2, but I also tried Python 2.5 so that I could use the python-rest-client with the included version of Httplib2. I see the same problem in either case.

The code is simple, matching the documented use:

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')

I've looked at the resulting HTTP requests from the browser tool and from my code and I can't see why one works and the other doesn't. This is the trace I receive:

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: ''

What's breaking? What do I do about it? Actually, I'd settle for advice on debugging it. I've changed the domain in my script and pointed it at my own machine so I could view the request. I've viewed/modified the Firefox requests in BurpProxy to make them match my script requests. The modified Burp requests still work and the Python requests still don't.

Apparently the issue is that the server expects there to be some message body for DELETE requests. That's an unusual expectation for a DELETE, but by specifying Content-Length:0 in the headers, I'm able to successfully perform DELETEs.

Somewhere along the way (in python-rest-client or httplib2), the Content-Length header is wiped out if I try to do:

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'})

Just to prove the concept, I went to the point in the stack trace where the request was happening:

File "/home/fmk/python/rest-client/src/httplib2/__init__.py", line 897, in _conn_request
response = conn.getresponse()

I printed the headers parameter there to confirm that the content length wasn't there, then I added:

if(method == 'DELETE'):
     headers['Content-Length'] = '0'

before the request.

I think the real answer is that the service is wonky, but at least I got to know httplib2 a little better. I've seen some other confused people looking for help with REST and Python, so hopefully I'm not the only one who got something out of this.

The following script correctly produces 404 response from the server:

#!/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 server must return it. Or at least send 411 Length Required response.

curl -H 'Content-length: 0' -X DELETE \
  http://www.thomas-bayer.com/sqlrest/CUSTOMER/85

Returns correctly 404 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM