Repository navigation
Expand file tree
/
Copy pathtest_httparse.py
More file actions
102 lines (78 loc) · 2.61 KB
/
Copy pathtest_httparse.py
File metadata and controls
102 lines (78 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
from __future__ import annotations
from collections import defaultdict
from dataclasses import dataclass
from typing import Dict, Set, Type
import pytest
from httparse import RequestParser, ParsedRequest, InvalidHTTPVersion, InvalidHeaderName
Headers = Dict[str, Set[bytes]]
@dataclass(frozen=True)
class ParsedResultWrapper:
method: str
path: str
version: int
headers: Headers
body_start_offset: int
@classmethod
def from_res(cls, res: ParsedRequest) -> ParsedResultWrapper:
headers: Dict[str, Set[bytes]] = defaultdict(set)
for header in res.headers:
for value in header.value.split(b","):
headers[header.name].add(value)
return cls(
method=res.method,
path=res.path,
version=res.version,
headers=headers,
body_start_offset=res.body_start_offset,
)
@pytest.mark.parametrize(
"buff,expected",
[
(
b"GET /index.html HTTP/1.1\r\nHost: example.domain\r\n\r\n",
ParsedResultWrapper(method="GET", path="/index.html", version=1, headers={"Host": {b"example.domain"}}, body_start_offset=50),
),
(
b"PUT / HTTP/1.1\r\nX-Foo: foo1,foo2\r\nX-Bar: bar\r\nX-Foo: foo3\r\n\r\n",
ParsedResultWrapper(method="PUT", path="/", version=1, headers={"X-Bar": {b"bar"}, "X-Foo": {b"foo1", b"foo2", b"foo3"}}, body_start_offset=61),
),
],
)
def test_parse_complete(
buff: bytes,
expected: ParsedResultWrapper,
) -> None:
parser = RequestParser()
parsed = parser.parse(buff)
assert parsed is not None
got = ParsedResultWrapper.from_res(parsed)
assert got == expected
def test_parse_partial() -> None:
parser = RequestParser()
parsed = parser.parse(b"GET /index.html HTTP/1.1\r\nHost")
assert parsed is None
parsed = parser.parse(b"GET /index.html HTTP/1.1\r\nHost: example.domain\r\n\r\n")
assert parsed is not None
def test_parse_bytearray() -> None:
parser = RequestParser()
parsed = parser.parse(bytearray(b"GET /index.html HTTP/1.1\r\nHost: example.domain\r\n\r\n"))
assert parsed is not None
@pytest.mark.parametrize(
"buff,exc", [
(b"GET /index.html HTTP/1.2", InvalidHTTPVersion),
("GET /index.html HTTP/1.1\r\nX-Café: example.domain\r\n\r\n".encode(), InvalidHeaderName)
]
)
def test_parsing_exceptions(
buff: bytes,
exc: Type[Exception]
) -> None:
parser = RequestParser()
with pytest.raises(exc):
parser.parse(buff)
if __name__ == "__main__":
pytest.main(
[
__file__,
]
)