Skip to content

Commit 301a09b

Browse files
committed
Allow user specification of max_headers, etc.
Users can specify `max_headers`, `max_line_size`, and `max_field_size` via `app.make_handler()`. Fixes #909.
1 parent b094199 commit 301a09b

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

aiohttp/server.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ class ServerHttpProtocol(aiohttp.StreamProtocol):
7373
:param str access_log_format: access log format string
7474
7575
:param loop: Optional event loop
76+
77+
:param int max_line_size: Optional maximum header line size
78+
79+
:param int max_field_size: Optional maximum header field size
80+
81+
:param int max_headers: Optional maximum header size
7682
"""
7783
_request_count = 0
7884
_request_handler = None
@@ -81,9 +87,6 @@ class ServerHttpProtocol(aiohttp.StreamProtocol):
8187
_keep_alive_handle = None # keep alive timer handle
8288
_timeout_handle = None # slow request timer handle
8389

84-
_request_prefix = aiohttp.HttpPrefixParser() # HTTP method parser
85-
_request_parser = aiohttp.HttpRequestParser() # default request parser
86-
8790
def __init__(self, *, loop=None,
8891
keep_alive=75, # NGINX default value is 75 secs
8992
keep_alive_on=True,
@@ -103,6 +106,14 @@ def __init__(self, *, loop=None,
103106
self._timeout = timeout # slow request timeout
104107
self._loop = loop if loop is not None else asyncio.get_event_loop()
105108

109+
parser_kwargs = {}
110+
for kwarg in ['max_line_size', 'max_field_size', 'max_headers']:
111+
if kwarg in kwargs:
112+
parser_kwargs[kwarg] = kwargs.pop(kwarg)
113+
114+
self._request_prefix = aiohttp.HttpPrefixParser()
115+
self._request_parser = aiohttp.HttpRequestParser(**parser_kwargs)
116+
106117
self.logger = log or logger
107118
self.debug = debug
108119
self.access_log = access_log

tests/test_web_functional.py

+43-3
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,18 @@ def find_unused_port(self):
4343

4444
@asyncio.coroutine
4545
def create_server(self, method, path, handler=None, ssl_ctx=None,
46-
logger=log.server_logger):
47-
app = web.Application(loop=self.loop)
46+
logger=log.server_logger, handler_kwargs=None):
47+
app = web.Application(
48+
loop=self.loop)
4849
if handler:
4950
app.router.add_route(method, path, handler)
5051

5152
port = self.find_unused_port()
5253
self.handler = app.make_handler(
5354
keep_alive_on=False,
5455
access_log=log.access_logger,
55-
logger=logger)
56+
logger=logger,
57+
**(handler_kwargs or {}))
5658
srv = yield from self.loop.create_server(
5759
self.handler, '127.0.0.1', port, ssl=ssl_ctx)
5860
protocol = "https" if ssl_ctx else "http"
@@ -776,6 +778,44 @@ def go():
776778

777779
self.loop.run_until_complete(go())
778780

781+
def test_large_header(self):
782+
783+
@asyncio.coroutine
784+
def handler(request):
785+
return web.Response()
786+
787+
@asyncio.coroutine
788+
def go():
789+
_, srv, url = yield from self.create_server('GET', '/', handler)
790+
headers = {'Long-Header': 'ab' * 8129}
791+
resp = yield from request('GET', url,
792+
headers=headers,
793+
loop=self.loop)
794+
self.assertEqual(400, resp.status)
795+
yield from resp.release()
796+
797+
self.loop.run_until_complete(go())
798+
799+
def test_large_header_allowed(self):
800+
801+
@asyncio.coroutine
802+
def handler(request):
803+
return web.Response()
804+
805+
@asyncio.coroutine
806+
def go():
807+
handler_kwargs = {'max_field_size': 81920}
808+
_, srv, url = yield from self.create_server(
809+
'GET', '/', handler, handler_kwargs=handler_kwargs)
810+
headers = {'Long-Header': 'ab' * 8129}
811+
resp = yield from request('GET', url,
812+
headers=headers,
813+
loop=self.loop)
814+
self.assertEqual(200, resp.status)
815+
yield from resp.release()
816+
817+
self.loop.run_until_complete(go())
818+
779819
def test_get_with_empty_arg_with_equal(self):
780820

781821
@asyncio.coroutine

0 commit comments

Comments
 (0)