411 ответ приводит к исключению в Session.send
ОБНОВЛЕНИЕ: добрые люди, разрабатывающие Requests.py, находятся на рассмотрении.
Мы взаимодействуем (тестируем) со службой HTTP, которая отвечает кодом состояния 411 (длина обязательна), если при наличии тела запроса не был предоставлен заголовок запроса Content-Length; Этого следует ожидать в соответствии с RFC 2616.
Проблема, с которой мы столкнулись, связана с модулем Python Requests (curl работает как положено). При отправке некорректного запроса (без Content-Length при наличии тела запроса) служба отвечает 411, и соединение закрывается удаленной конечной точкой ( Connection: close). Это, в свою очередь, вызывает исключение из метода Requests Session.send, и мы не можем получить код состояния ответа HTTP для проверки.
Можно ли остановить эту ситуацию (исключение) и получить код состояния ответа HTTP без изменения службы HTTP?
Код
from requests import Request, Session
endpoint = "http://api.corvusoft.co.uk/resources"
request_body = '{ "data": {"core-temperature": "1,430", "core-temperature-units": "celsius", ... } }'
request = Request('POST', endpoint, data=request_body, headers={"Connection": "close"})
prepared_request = request.prepare()
del prepared_request.headers['Content-Length']
session = Session()
response = session.send(prepared_request)
print response.status_code
Трассировки стека
Scenario: HTTP PUT without Content-Length
Given I have initialised the core sensors
And I perform a HTTP "POST" request to "/readings" with headers "Content-Type: application/vnd.api+json; charset=utf-8, Accept: application/vnd.api+json":
| """ |
| " { "data": { " |
| " "id": "c0f22109-d258-4458-a3f5-0d16b2f55487", " |
| " "value": "acceptance-test" " |
| " } " |
| " } " |
| """ |
When I perform a HTTP "PUT" request to "/queues/c0f22109-d258-4458-a3f5-0d16b2f55487" without header "Content-Length":
| """ |
| " { "data": { " |
| " "ttl": 30, " |
| " "id": "c0f22109-d258-4458-a3f5-0d16b2f55487" " |
| " } " |
| " } " |
| """ |
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/lettuce/core.py", line 144, in __call__
ret = self.function(self.step, *args, **kw)
File "/Users/Corvusoft/Development/test/acceptance/features/step_definitions/request.py", line 30, in i_perform_a_http_method_request_to_path_without_header_and_body
i_perform_a_http_method_request_to_path_with_headers_and_body( step, method, path, "Accept: application/vnd.api+json, Content-Type: application/vnd.api+json; charset=utf-8", True )
File "/Users/Corvusoft/Development/test/acceptance/features/step_definitions/request.py", line 91, in i_perform_a_http_method_request_to_path_with_headers_and_body
response = session.send( request )
File "/Library/Python/2.7/site-packages/requests/sessions.py", line 573, in send
r = adapter.send(request, **kwargs)
File "/Library/Python/2.7/site-packages/requests/adapters.py", line 415, in send
raise ConnectionError(err, request=request)
ConnectionError: [Errno 32] Broken pipe
Запрос
POST /resources HTTP/1.1
Host: api.corvusoft.co.uk
Connection: close
Content-Type: application/vnd.api+json; charset=utf-8
Accept: application/vnd.api+json
Accept-Charset: utf-8
{ "data": {"core-temperature": "1,430", "core-temperature-units": "celsius", ... } }
отклик
HTTP/1.1 411 Length Required
Connection: close
Content-Type: application/vnd.api+json; charset=utf-8
Content-Length: 304
{"errors":[{"status":"411","title":"Content Length Required", "description": "The server refuses to accept the request without a defined Content-Length. The client MAY repeat the request if it adds a valid Content-Length header field containing the length of the message-body in the request message."}]}
Среда
Python: 2.7.5
Запросы: 2.5.3