Repository: theelous3/asks

Issue:
KeyError: 'transfer-encoding'
```
Traceback (most recent call last):
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/request.py", line 549, in _catch_response
    if int(resp_data['headers']['content-length']) > 0:
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/req_structs.py", line 79, in __getitem__
    return self._store[key.lower()][1]
KeyError: 'content-length'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curio/kernel.py", line 826, in _run_coro
    trap = current._send(current.next_value)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curio/task.py", line 96, in _task_runner
    return await coro
  File "/home/laura/dev/discord/automoderator/automoderator/core/engine.py", line 133, in _handle_rule
    await fn(ctx, **kwargs)
  File "/home/laura/dev/discord/automoderator/automoderator/core/engine.py", line 175, in action_delete_message
    await msg.delete()
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curious/dataclasses/message.py", line 231, in delete
    await self._bot.http.delete_message(self.channel.id, self.id)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curious/http/httpclient.py", line 596, in delete_message
    data = await self.delete(url, "messages:{}".format(channel_id))
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curious/http/httpclient.py", line 378, in delete
    return await self.request(("DELETE", bucket), method="DELETE", path=url, *args, **kwargs)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curious/http/httpclient.py", line 251, in request
    response = await self._make_request(*args, **kwargs)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/curious/http/httpclient.py", line 212, in _make_request
    return await self.session.request(*args, headers=headers, **kwargs)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/sessions.py", line 156, in request
    sock, r = await req_obj.make_request()
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/request.py", line 203, in make_request
    response_obj = await self._request_io(req, req_body, hconnection)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/request.py", line 240, in _request_io
    response_obj = await self._catch_response(hconnection)
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/request.py", line 553, in _catch_response
    if resp_data['headers']['transfer-encoding'] == 'chunked':
  File "/home/laura/.local/share/virtualenvs/automoderator-nZfczLQS/lib/python3.6/site-packages/asks/req_structs.py", line 79, in __getitem__
    return self._store[key.lower()][1]
KeyError: 'transfer-encoding'
```

Errors when a HTTP server sends neither a Content-Length nor a Transfer-Encoding.

Discussion:

Patch:
diff --git a/asks/request.py b/asks/request.py
index 8361383..c1cfe6c 100644
--- a/asks/request.py
+++ b/asks/request.py
@@ -544,13 +544,20 @@ class Request:
                 except (KeyError, AttributeError):
                     resp_data['headers']['set-cookie'] = [str(header[1],
                                                           'utf-8')]
+
+        # check whether we should receive body according to RFC 7230
+        # https://tools.ietf.org/html/rfc7230#section-3.3.3
         get_body = False
         try:
             if int(resp_data['headers']['content-length']) > 0:
                 get_body = True
         except KeyError:
-            if resp_data['headers']['transfer-encoding'] == 'chunked':
-                get_body = True
+            try:
+                if resp_data['headers']['transfer-encoding'] == 'chunked':
+                    get_body = True
+            except KeyError:
+                if resp_data['headers']['connection'] == 'close':
+                    get_body = True
 
         if get_body:
             if self.callback is not None:


Test patch:
diff --git a/tests/test_asks_curio.py b/tests/test_asks_curio.py
index f255e48..b504c38 100644
--- a/tests/test_asks_curio.py
+++ b/tests/test_asks_curio.py
@@ -190,6 +190,13 @@ async def test_stream():
     assert len(img) == 8090
 
 
+# Test connection close without content-length and transfer-encoding
+@curio_run
+async def test_connection_close():
+    r = await asks.get('https://www.ua-region.com.ua/search/?q=rrr')
+    assert r.text
+
+
 # Test callback
 callback_data = b''
 async def callback_example(chunk):
diff --git a/tests/test_asks_trio.py b/tests/test_asks_trio.py
index 8a87bd8..322edd3 100644
--- a/tests/test_asks_trio.py
+++ b/tests/test_asks_trio.py
@@ -193,6 +193,13 @@ async def test_stream():
     assert len(img) == 8090
 
 
+# Test connection close without content-length and transfer-encoding
+@trio_run
+async def test_connection_close():
+    r = await asks.get('https://www.ua-region.com.ua/search/?q=rrr')
+    assert r.text
+
+
 # Test callback
 callback_data = b''
 async def callback_example(chunk):