Skip to content

Commit eda2d3f

Browse files
committed
Replacing httptools with h11.
1 parent 6e3fbad commit eda2d3f

File tree

2 files changed

+29
-34
lines changed

2 files changed

+29
-34
lines changed

mocket/mockhttp.py

+28-33
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import re
22
import time
3+
from functools import cached_property
34
from http.server import BaseHTTPRequestHandler
45
from urllib.parse import parse_qs, unquote, urlsplit
56

6-
from httptools.parser import HttpRequestParser
7+
from h11 import SERVER, Connection, Data
8+
from h11 import Request as H11Request
79

810
from .compat import ENCODING, decode_from_bytes, do_the_magic, encode_to_bytes
911
from .mocket import Mocket, MocketEntry
@@ -19,61 +21,54 @@
1921
ASCII = "ascii"
2022

2123

22-
class Protocol:
23-
def __init__(self):
24-
self.url = None
25-
self.body = None
26-
self.headers = {}
27-
28-
def on_header(self, name: bytes, value: bytes):
29-
self.headers[name.decode(ASCII)] = value.decode(ASCII)
30-
31-
def on_body(self, body: bytes):
32-
try:
33-
self.body = body.decode(ENCODING)
34-
except UnicodeDecodeError:
35-
self.body = body
36-
37-
def on_url(self, url: bytes):
38-
self.url = url.decode(ASCII)
39-
40-
4124
class Request:
42-
_protocol = None
4325
_parser = None
26+
_event = None
4427

4528
def __init__(self, data):
46-
self._protocol = Protocol()
47-
self._parser = HttpRequestParser(self._protocol)
29+
self._parser = Connection(SERVER)
4830
self.add_data(data)
4931

5032
def add_data(self, data):
51-
self._parser.feed_data(data)
33+
self._parser.receive_data(data)
5234

5335
@property
36+
def event(self):
37+
if not self._event:
38+
event = self._parser.next_event()
39+
self._event = event
40+
return self._event
41+
42+
@cached_property
5443
def method(self):
55-
return self._parser.get_method().decode(ASCII)
44+
return self.event.method.decode(ASCII)
5645

57-
@property
46+
@cached_property
5847
def path(self):
59-
return self._protocol.url
48+
return self.event.target.decode(ASCII)
6049

61-
@property
50+
@cached_property
6251
def headers(self):
63-
return self._protocol.headers
52+
return {k.decode(ASCII): v.decode(ASCII) for k, v in self.event.headers}
6453

65-
@property
54+
@cached_property
6655
def querystring(self):
67-
parts = self._protocol.url.split("?", 1)
56+
parts = self.path.split("?", 1)
6857
return (
6958
parse_qs(unquote(parts[1]), keep_blank_values=True)
7059
if len(parts) == 2
7160
else {}
7261
)
7362

74-
@property
63+
@cached_property
7564
def body(self):
76-
return self._protocol.body
65+
while True:
66+
event = self._parser.next_event()
67+
if isinstance(event, H11Request):
68+
self._event = event
69+
elif isinstance(event, Data):
70+
break
71+
return event.data.decode(ENCODING)
7772

7873
def __str__(self):
7974
return f"{self.method} - {self.path} - {self.headers}"

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ dependencies = [
2929
"python-magic>=0.4.5",
3030
"decorator>=4.0.0",
3131
"urllib3>=1.25.3",
32-
"httptools",
32+
"h11",
3333
]
3434
dynamic = ["version"]
3535

0 commit comments

Comments
 (0)