mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-01 10:11:30 +08:00
* Add InvalidChunkExtension to treq_asgi.py and fast parser support - Add InvalidChunkExtension import and exception mapping for proper test coverage of bare CR rejection in chunk extensions per RFC 9112 7.1.1 - Add fast parser (H1CProtocol) support to treq_asgi.py and the ASGI invalid request tests - Fast parser now receives limit configuration (limit_request_line, limit_request_fields, limit_request_field_size) - Handle gunicorn_h1c's multiple ParseError classes from different modules - Skip tests where fast parser has different validation than Python parser * Handle gunicorn_h1c limit exceptions in ASGI protocol Add handling for gunicorn_h1c.LimitRequestLine and gunicorn_h1c.LimitRequestHeaders exceptions, matching the behavior of the Python parser exceptions with appropriate HTTP status codes: - LimitRequestLine: 414 URI Too Long - LimitRequestHeaders: 431 Request Header Fields Too Large * Refactor data_received to fix too-many-return-statements lint
83 lines
2.9 KiB
Python
83 lines
2.9 KiB
Python
#
|
|
# This file is part of gunicorn released under the MIT license.
|
|
# See the NOTICE for more information.
|
|
|
|
"""Test invalid HTTP requests against ASGI callback parser.
|
|
|
|
Runs the same .http test files as test_invalid_requests.py but using
|
|
the ASGI callback parsers (PythonProtocol and H1CProtocol).
|
|
"""
|
|
|
|
import glob
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from gunicorn.http.errors import (
|
|
InvalidSchemeHeaders,
|
|
ObsoleteFolding,
|
|
)
|
|
import treq_asgi
|
|
|
|
dirname = os.path.dirname(__file__)
|
|
reqdir = os.path.join(dirname, "requests", "invalid")
|
|
httpfiles = glob.glob(os.path.join(reqdir, "*.http"))
|
|
|
|
# Tests that require features not supported by callback parser
|
|
SKIP_TESTS = {
|
|
# Tests requiring header_map config (underscore handling)
|
|
'chunked_07.http', '040.http',
|
|
# Tests for features not in callback parser
|
|
'008.http', # Invalid request target validation
|
|
'012.http', # Invalid request target validation
|
|
'016.http', # URI bracket validation
|
|
'020.http', # Space before colon in header name
|
|
'022.http', # Request target validation
|
|
}
|
|
|
|
# Config flags incompatible with callback parser
|
|
INCOMPATIBLE_FLAGS = ('permit_obsolete_folding', 'strip_header_spaces')
|
|
|
|
# Exceptions only raised by Python WSGI parser
|
|
WSGI_ONLY_EXCEPTIONS = (ObsoleteFolding, InvalidSchemeHeaders)
|
|
|
|
# Tests where fast parser has different validation than Python parser
|
|
FAST_PARSER_SKIP_TESTS = {
|
|
'014.http', # InvalidHeader - fast parser accepts
|
|
'015.http', # InvalidHeader - fast parser accepts
|
|
'023.http', # InvalidHeader - fast parser accepts
|
|
'024.http', # InvalidHeader - fast parser accepts
|
|
'prefix_03.http', # InvalidHeader - fast parser accepts
|
|
'prefix_04.http', # InvalidHeader - fast parser accepts
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize("fname", httpfiles)
|
|
def test_asgi_parser(fname, http_parser):
|
|
"""Test invalid HTTP requests with ASGI callback parsers."""
|
|
basename = os.path.basename(fname)
|
|
if basename in SKIP_TESTS:
|
|
pytest.skip(f"Test {basename} not supported by callback parser")
|
|
|
|
# Skip fast parser tests for files with known different validation
|
|
if http_parser == 'fast' and basename in FAST_PARSER_SKIP_TESTS:
|
|
pytest.skip(f"Fast parser has different validation for {basename}")
|
|
|
|
env = treq_asgi.load_py(os.path.splitext(fname)[0] + ".py", http_parser=http_parser)
|
|
expect = env["request"]
|
|
cfg = env["cfg"]
|
|
|
|
# Skip tests that use incompatible config flags
|
|
for flag in INCOMPATIBLE_FLAGS:
|
|
if getattr(cfg, flag, False):
|
|
pytest.skip(f"Callback parser incompatible with {flag}")
|
|
|
|
# Skip tests expecting WSGI-only exceptions
|
|
if expect in WSGI_ONLY_EXCEPTIONS or (
|
|
isinstance(expect, type) and issubclass(expect, WSGI_ONLY_EXCEPTIONS)
|
|
):
|
|
pytest.skip(f"Callback parser does not raise {expect.__name__}")
|
|
|
|
req = treq_asgi.badrequest(fname)
|
|
req.check(cfg, expect, http_parser=http_parser)
|