httpdbg 2.4.0__tar.gz → 2.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {httpdbg-2.4.0 → httpdbg-2.4.1}/PKG-INFO +1 -1
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/__init__.py +1 -1
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/record.py +20 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/recordhttp1.py +15 -2
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/recordhttp2.py +20 -1
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg.egg-info/PKG-INFO +1 -1
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg.egg-info/SOURCES.txt +1 -0
- httpdbg-2.4.1/tests/test_serialization.py +82 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/LICENSE +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/README.md +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/__main__.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/args.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/env.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/exception.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/export.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/__init__.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/aiohttp.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/all.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/external.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/fastapi.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/flask.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/generic.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/h2.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/http.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/httpx.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/pytest.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/requests.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/socket.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/starlette.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/template_sitecustomize.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/unittest.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/urllib3.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/utils.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/hooks/uvicorn.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/http_status_code.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/initiator.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/log.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/mode_console.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/mode_module.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/mode_script.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/preview.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/records.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/server.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/utils.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/__init__.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/app.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/api.js +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/column.css +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/configuration.css +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/configuration.js +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/detail.css +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/favicon.ico +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/filter.js +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/chevron-direction-top-outline-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/download-install-line-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/engine-gears-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/eye-blind-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/eye-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/files-papers-outline-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/filter-outline-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/lock-line-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/lock-open-line-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/math-multiplication-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/push-pin-green-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/recycle-bin-line-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/wait-sandclock-icon.svg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/index.htm +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/main.js +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/mustache.min.js +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/render.js +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/style.css +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/table.css +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg.egg-info/dependency_links.txt +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg.egg-info/entry_points.txt +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg.egg-info/top_level.txt +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/pyproject.toml +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/setup.cfg +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_api.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_cli.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_context_manager.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_aiohttp.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_h2.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_httpx.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_pytest.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_requests.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_unittest.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_hook_urllib3.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_initiator.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_mode_console.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_mode_module_pytest.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_mode_script.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_multiprocess.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_preview.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_pyhttpdbg_server.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_server.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_server_hook_fastapi.py +0 -0
- {httpdbg-2.4.0 → httpdbg-2.4.1}/tests/test_server_hook_flask.py +0 -0
|
@@ -238,3 +238,23 @@ class HTTPRecord(ABC):
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
return json.dumps(payload).encode("utf-8")
|
|
241
|
+
|
|
242
|
+
def __eq__(self, other: object) -> bool:
|
|
243
|
+
if not isinstance(other, HTTPRecord):
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
self.url == other.url
|
|
248
|
+
and self.method == other.method
|
|
249
|
+
and self.status_code == other.status_code
|
|
250
|
+
and self.protocol == other.protocol
|
|
251
|
+
and self.tag == other.tag
|
|
252
|
+
and self.initiator_id == other.initiator_id
|
|
253
|
+
and self.group_id == other.group_id
|
|
254
|
+
and self.is_client == other.is_client
|
|
255
|
+
and self.http100 == other.http100
|
|
256
|
+
and type(self.exception) is type(other.exception)
|
|
257
|
+
and str(self.exception) == str(other.exception)
|
|
258
|
+
and self.request == other.request
|
|
259
|
+
and self.response == other.response
|
|
260
|
+
)
|
|
@@ -77,6 +77,12 @@ class HTTP1RecordReqResp(HTTPRecordReqResp):
|
|
|
77
77
|
self.last_update = datetime.datetime.now(datetime.timezone.utc)
|
|
78
78
|
self._rawdata = value
|
|
79
79
|
|
|
80
|
+
def __eq__(self, other: object) -> bool:
|
|
81
|
+
if not isinstance(other, HTTP1RecordReqResp):
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
return self.rawdata == other.rawdata and self.last_update == other.last_update
|
|
85
|
+
|
|
80
86
|
|
|
81
87
|
class HTTP1RecordRequest(HTTPRecordRequest, HTTP1RecordReqResp):
|
|
82
88
|
def __init__(self) -> None:
|
|
@@ -211,7 +217,8 @@ class HTTP1Record(HTTPRecord):
|
|
|
211
217
|
"sent": base64.b64encode(
|
|
212
218
|
self.request.rawdata if self.is_client else self.response.rawdata,
|
|
213
219
|
).decode("ascii"),
|
|
214
|
-
"
|
|
220
|
+
"last_update_request": self.request.last_update.isoformat(),
|
|
221
|
+
"last_update_response": self.response.last_update.isoformat(),
|
|
215
222
|
}
|
|
216
223
|
|
|
217
224
|
@staticmethod
|
|
@@ -224,6 +231,12 @@ class HTTP1Record(HTTPRecord):
|
|
|
224
231
|
data["is_client"],
|
|
225
232
|
)
|
|
226
233
|
http1record.id = data["id"]
|
|
227
|
-
http1record.receive_data(base64.b64decode(data["received"]))
|
|
228
234
|
http1record.send_data(base64.b64decode(data["sent"]))
|
|
235
|
+
http1record.receive_data(base64.b64decode(data["received"]))
|
|
236
|
+
http1record.request.last_update = datetime.datetime.fromisoformat(
|
|
237
|
+
data["last_update_request"]
|
|
238
|
+
)
|
|
239
|
+
http1record.response.last_update = datetime.datetime.fromisoformat(
|
|
240
|
+
data["last_update_response"]
|
|
241
|
+
)
|
|
229
242
|
return http1record
|
|
@@ -42,6 +42,16 @@ class HTTP2RecordReqResp(HTTPRecordReqResp):
|
|
|
42
42
|
self.get_header("Content-Encoding"),
|
|
43
43
|
)
|
|
44
44
|
|
|
45
|
+
def __eq__(self, other: object) -> bool:
|
|
46
|
+
if not isinstance(other, HTTP2RecordReqResp):
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
self.headers == other.headers
|
|
51
|
+
and self.content == other.content
|
|
52
|
+
and self.last_update == other.last_update
|
|
53
|
+
)
|
|
54
|
+
|
|
45
55
|
|
|
46
56
|
class HTTP2RecordRequest(HTTPRecordRequest, HTTP2RecordReqResp):
|
|
47
57
|
|
|
@@ -129,7 +139,8 @@ class HTTP2Record(HTTPRecord):
|
|
|
129
139
|
"headers": [header.to_json() for header in self.response.headers],
|
|
130
140
|
"content": base64.b64encode(self.response.content).decode("ascii"),
|
|
131
141
|
},
|
|
132
|
-
"
|
|
142
|
+
"last_update_request": self.request.last_update.isoformat(),
|
|
143
|
+
"last_update_response": self.response.last_update.isoformat(),
|
|
133
144
|
}
|
|
134
145
|
|
|
135
146
|
@staticmethod
|
|
@@ -146,8 +157,16 @@ class HTTP2Record(HTTPRecord):
|
|
|
146
157
|
HTTPDBGHeader.from_json(header) for header in data["request"]["headers"]
|
|
147
158
|
]
|
|
148
159
|
http2record.request.content = base64.b64decode(data["request"]["content"])
|
|
160
|
+
http2record.request.last_update = datetime.datetime.fromisoformat(
|
|
161
|
+
data["last_update_request"]
|
|
162
|
+
)
|
|
163
|
+
|
|
149
164
|
http2record.response._headers = [
|
|
150
165
|
HTTPDBGHeader.from_json(header) for header in data["response"]["headers"]
|
|
151
166
|
]
|
|
152
167
|
http2record.response.content = base64.b64decode(data["response"]["content"])
|
|
168
|
+
http2record.response.last_update = datetime.datetime.fromisoformat(
|
|
169
|
+
data["last_update_response"]
|
|
170
|
+
)
|
|
171
|
+
|
|
153
172
|
return http2record
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
import pytest
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
from httpdbg.hooks.all import httprecord
|
|
6
|
+
from httpdbg.hooks.recordhttp1 import HTTP1Record
|
|
7
|
+
from httpdbg.hooks.recordhttp2 import HTTP2Record
|
|
8
|
+
from httpdbg.utils import HTTPDBGCookie
|
|
9
|
+
from httpdbg.utils import HTTPDBGHeader
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
from tests.demo_http2 import http2_httpbin_server
|
|
13
|
+
from tests.utils import get_free_tcp_port
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture(scope="module")
|
|
17
|
+
def httpbin2():
|
|
18
|
+
host = "127.0.0.1"
|
|
19
|
+
port = get_free_tcp_port(host)
|
|
20
|
+
with http2_httpbin_server(host, port) as url:
|
|
21
|
+
yield url
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.mark.serialization
|
|
25
|
+
def test_serialization_http1record(httpbin):
|
|
26
|
+
with httprecord() as records:
|
|
27
|
+
requests.get(
|
|
28
|
+
f"{httpbin.url}/cookies/set/confiture/oignon",
|
|
29
|
+
cookies={"jam": "strawberry"},
|
|
30
|
+
allow_redirects=False,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
assert len(records) == 1
|
|
34
|
+
http_record = records[0]
|
|
35
|
+
http_record_copy = HTTP1Record.from_json(http_record.to_json())
|
|
36
|
+
|
|
37
|
+
assert HTTPDBGCookie("jam", "strawberry") in http_record_copy.request.cookies
|
|
38
|
+
|
|
39
|
+
assert (
|
|
40
|
+
HTTPDBGCookie(
|
|
41
|
+
"confiture",
|
|
42
|
+
"oignon",
|
|
43
|
+
[
|
|
44
|
+
{"attr": "/", "name": "path"},
|
|
45
|
+
],
|
|
46
|
+
)
|
|
47
|
+
in http_record_copy.response.cookies
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
assert http_record_copy == http_record
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pytest.mark.serialization
|
|
54
|
+
def test_serialization_http2record(httpbin2):
|
|
55
|
+
with httprecord() as records:
|
|
56
|
+
client = httpx.Client(http2=True, verify=False)
|
|
57
|
+
client.post(f"{httpbin2}/post", content="abc")
|
|
58
|
+
|
|
59
|
+
assert len(records) == 1
|
|
60
|
+
http_record = records[0]
|
|
61
|
+
http_record_copy = HTTP2Record.from_json(http_record.to_json())
|
|
62
|
+
|
|
63
|
+
assert http_record_copy.protocol == "HTTP/2"
|
|
64
|
+
|
|
65
|
+
assert http_record_copy.method.upper() == "POST"
|
|
66
|
+
assert http_record_copy.status_code == 200
|
|
67
|
+
|
|
68
|
+
assert HTTPDBGHeader("content-length", "3") in http_record_copy.request.headers
|
|
69
|
+
assert http_record_copy.request.cookies == []
|
|
70
|
+
assert http_record_copy.request.content == b"abc"
|
|
71
|
+
|
|
72
|
+
assert http_record_copy.last_update == http_record.last_update
|
|
73
|
+
|
|
74
|
+
assert http_record_copy == http_record
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.mark.serialization
|
|
78
|
+
def test_serialization_compatibility():
|
|
79
|
+
http1record = HTTP1Record("a", "b")
|
|
80
|
+
http2record = HTTP2Record("a", "b")
|
|
81
|
+
assert not (http1record == http2record)
|
|
82
|
+
assert not (http2record == http1record)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/chevron-direction-top-outline-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-2.4.0 → httpdbg-2.4.1}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|