Ошибка Python BadStatusLine на определенных запросах DELETE

1

Я пытаюсь использовать 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, он терпит неудачу. Я могу использовать клиент REST Firefox для выполнения запросов 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: ''

Какое нарушение? Что мне с этим делать? На самом деле, я бы согласился на консультацию по его отладке. Я изменил домен в своем скрипте и указал его на свою собственную машину, чтобы я мог просмотреть запрос. Я просмотрел/изменил запросы Firefox в BurpProxy, чтобы они соответствовали моим запросам скриптов. Измененные запросы Burp по-прежнему работают, и запросы Python по-прежнему не работают.

Теги:
rest
httplib2

2 ответа

4

По-видимому, проблема в том, что сервер ожидает, что для запросов DELETE будет некоторый текст сообщения. Это необычное ожидание для DELETE, но, указав Content-Length: 0 в заголовках, я могу успешно выполнить DELETE.

Где-то по пути (в python-rest-client или 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 возвращает непустой ответ.
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 не является обязательным; HTTP-сервер должен вернуть его. Или, по крайней мере, отправить 411 Length Required response.

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"?> <Resource xmlns: xlink = " w3. org / 1999 / xlink "> <удаленный> 85 </ удаленный> </ resource> Кроме того, не всегда происходит сбой запроса Python при обработке ответа. Элемент успешно удален запросами Firefox (последующие запросы GET получают 404 ответа), но запись все еще существует после попытки удаления Python.
  • 0
    @Mikey 0: на сервере могут быть какие-то меры антибота. Это может проверить пользовательский агент, реферер, куки и т. Д.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню