From 5e777696447f1895d67625c913398795308de31f Mon Sep 17 00:00:00 2001 From: Trygve Aaberge Date: Sat, 14 Jan 2023 17:35:23 +0100 Subject: Support multiple HTTP headers Port 3aa2c79 from master into new. --- slack/http.py | 11 +++++------ tests/test_http_request.py | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/slack/http.py b/slack/http.py index 7ec661e..a0baa74 100644 --- a/slack/http.py +++ b/slack/http.py @@ -84,12 +84,13 @@ async def http_request( return await http_request(url, options, timeout, max_retries - 1) raise HttpError(url, return_code, 0, err) - headers_end_index = out.index("\r\n\r\n") - headers = out[:headers_end_index].split("\r\n") - http_status = int(headers[0].split(" ")[1]) + parts = out.split("\r\n\r\nHTTP/") + last_header_part, body = parts[-1].split("\r\n\r\n", 1) + header_lines = last_header_part.split("\r\n") + http_status = int(header_lines[0].split(" ")[1]) if http_status == 429: - for header in headers[1:]: + for header in header_lines[1:]: name, value = header.split(":", 1) if name.lower() == "retry-after": retry_after = int(value.strip()) @@ -100,8 +101,6 @@ async def http_request( await sleep(retry_after * 1000) return await http_request(url, options, timeout) - body = out[headers_end_index + 4 :] - if http_status >= 400: raise HttpError(url, return_code, http_status, body) diff --git a/tests/test_http_request.py b/tests/test_http_request.py index 3a2e8cc..57b0c91 100644 --- a/tests/test_http_request.py +++ b/tests/test_http_request.py @@ -1,3 +1,4 @@ +from textwrap import dedent from unittest.mock import MagicMock, patch import pytest @@ -112,6 +113,33 @@ def test_http_request_error_retry_error(): assert excinfo.value.error == "" +def test_http_request_multiple_headers(): + url = "http://example.com" + coroutine = http_request(url, {}, 0) + future = coroutine.send(None) + assert isinstance(future, FutureProcess) + + response = "response" + body = ( + dedent( + f""" + HTTP/1.1 200 Connection established + + HTTP/2 200 + content-type: application/json; charset=utf-8 + + {response} + """ + ) + .strip() + .replace("\n", "\r\n") + ) + + with pytest.raises(StopIteration) as excinfo: + coroutine.send(("", 0, body, "")) + assert excinfo.value.value == response + + @patch.object(weechat, "hook_timer") def test_http_request_ratelimit(mock_method: MagicMock): url = "http://example.com" @@ -127,5 +155,7 @@ def test_http_request_ratelimit(mock_method: MagicMock): assert isinstance(coroutine.send((0,)), FutureProcess) - with pytest.raises(StopIteration): - coroutine.send(("", 0, "HTTP/2 200\r\n\r\n", "")) + response = "response" + with pytest.raises(StopIteration) as excinfo: + coroutine.send(("", 0, f"HTTP/2 200\r\n\r\n{response}", "")) + assert excinfo.value.value == response -- cgit