Repository: aio-libs/aiohttp

Issue:
If you send garbage via telnet you should receive a 400
On most server when you send non HTTP content to the server, the server reply by a 400 or close the connection.

Actually in aiohttp if you receive non HTTP content you got a stacktrace in the log and client receive a 500:

```
Traceback (most recent call last):
  File "/lib/python3.4/site-packages/aiohttp/server.py", line 241, in start
    yield from prefix.read()
  File "/lib/python3.4/site-packages/aiohttp/streams.py", line 505, in read
    result = yield from super().read()
  File "/lib/python3.4/site-packages/aiohttp/streams.py", line 365, in read
    yield from self._waiter
  File "/lib/python3.4/asyncio/futures.py", line 386, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/lib/python3.4/asyncio/tasks.py", line 287, in _wakeup
    value = future.result()
  File "/lib/python3.4/asyncio/futures.py", line 275, in result
    raise self._exception
  File "//lib/python3.4/site-packages/aiohttp/parsers.py", line 131, in feed_data
    self._parser.send(data)
  File "/lib/python3.4/site-packages/aiohttp/protocol.py", line 139, in __call__
    raw_data = yield from buf.waituntil(b' ', 12)
  File "/lib/python3.4/site-packages/aiohttp/parsers.py", line 374, in waituntil
    'Line is too long. %s' % bytes(self), limit)
aiohttp.errors.LineLimitExceededParserError: Line is too long. b'fdgdf\r\nfgddfg\r\n'
```

The main issue for me is the fact it's noisy in the log. 



Discussion:
Agree. We have catch the error in https://github.com/KeepSafe/aiohttp/blob/master/aiohttp/server.py#L241 and https://github.com/KeepSafe/aiohttp/blob/master/aiohttp/server.py#L253, return 400 HTTP status code and log traceback only in debug mode.

Would you prepare Pull Request?


Resolving patch:
diff --git a/aiohttp/server.py b/aiohttp/server.py
--- a/aiohttp/server.py
+++ b/aiohttp/server.py
@@ -280,6 +280,8 @@ def start(self):
                 if self.transport is not None:
                     yield from self.handle_error(exc.code, message,
                                                  None, exc, exc.headers)
+            except errors.LineLimitExceededParserError as exc:
+                yield from self.handle_error(400, message, None, exc)
             except Exception as exc:
                 yield from self.handle_error(500, message, None, exc)
             finally:


Test patch:
diff --git a/tests/test_http_server.py b/tests/test_http_server.py
--- a/tests/test_http_server.py
+++ b/tests/test_http_server.py
@@ -221,6 +221,17 @@ def test_bad_method(self):
         self.assertTrue(transport.write.mock_calls[0][1][0].startswith(
             b'HTTP/1.1 400 Bad Request\r\n'))
 
+    def test_line_too_long(self):
+        transport = unittest.mock.Mock()
+        srv = server.ServerHttpProtocol(loop=self.loop)
+        srv.connection_made(transport)
+
+        srv.reader.feed_data(b''.join([b'a' for _ in range(10000)]))
+
+        self.loop.run_until_complete(srv._request_handler)
+        self.assertTrue(transport.write.mock_calls[0][1][0].startswith(
+            b'HTTP/1.1 400 Bad Request\r\n'))
+
     def test_handle_error(self):
         transport = unittest.mock.Mock()
         srv = server.ServerHttpProtocol(loop=self.loop)