httpdbg 2.0.0__tar.gz → 2.0.2__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.0.0 → httpdbg-2.0.2}/PKG-INFO +1 -1
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/__init__.py +1 -2
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/__main__.py +4 -3
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/args.py +7 -2
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/aiohttp.py +1 -3
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/generic.py +2 -8
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/h2.py +3 -10
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/http.py +0 -1
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/httpx.py +2 -3
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/requests.py +1 -3
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/socket.py +4 -11
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/urllib3.py +1 -3
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/uvicorn.py +0 -3
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/initiator.py +64 -57
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg.egg-info/PKG-INFO +1 -1
- {httpdbg-2.0.0 → httpdbg-2.0.2}/LICENSE +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/README.md +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/env.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/exception.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/__init__.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/all.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/external.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/fastapi.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/flask.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/pytest.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/record.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/recordhttp1.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/recordhttp2.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/starlette.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/template_sitecustomize.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/unittest.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/hooks/utils.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/http_status_code.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/log.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/mode_console.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/mode_module.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/mode_script.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/preview.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/records.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/server.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/utils.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/__init__.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/api.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/app.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/api.js +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/column.css +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/configuration.css +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/configuration.js +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/detail.css +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/favicon.ico +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/filter.js +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/chevron-direction-top-outline-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/download-install-line-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/engine-gears-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/eye-blind-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/eye-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/files-papers-outline-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/filter-outline-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/information-mark-circle-outline-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/lock-line-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/lock-open-line-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/math-multiplication-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/push-pin-green-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/recycle-bin-line-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/wait-sandclock-icon.svg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/index.htm +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/main.js +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/mustache.min.js +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/render.js +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/style.css +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/table.css +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg.egg-info/SOURCES.txt +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg.egg-info/dependency_links.txt +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg.egg-info/entry_points.txt +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg.egg-info/top_level.txt +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/pyproject.toml +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/setup.cfg +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_api.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_cli.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_context_manager.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_aiohttp.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_h2.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_httpx.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_pytest.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_requests.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_unittest.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_hook_urllib3.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_initiator.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_mode_console.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_mode_module_pytest.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_mode_script.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_multiprocess.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_preview.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_pyhttpdbg_server.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_server.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_server_hook_fastapi.py +0 -0
- {httpdbg-2.0.0 → httpdbg-2.0.2}/tests/test_server_hook_flask.py +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
import sys
|
|
3
2
|
import time
|
|
4
3
|
|
|
@@ -24,7 +23,8 @@ def pyhttpdbg(params, subparams, test_mode=False):
|
|
|
24
23
|
|
|
25
24
|
url = f"http://{params.host}:{params.port}/{'?hi=on' if params.console else ''}"
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
if not params.no_banner:
|
|
27
|
+
print_msg(f" httpdbg - HTTP(S) requests available at {url}")
|
|
28
28
|
|
|
29
29
|
sys.path.insert(0, "") # to mimic the default python command behavior
|
|
30
30
|
|
|
@@ -39,7 +39,8 @@ def pyhttpdbg(params, subparams, test_mode=False):
|
|
|
39
39
|
run_console(records, test_mode)
|
|
40
40
|
|
|
41
41
|
if not (params.force_quit or test_mode):
|
|
42
|
-
|
|
42
|
+
if not params.no_banner:
|
|
43
|
+
print_msg(f" httpdbg - HTTP(S) requests available at {url}")
|
|
43
44
|
|
|
44
45
|
if params.keep_up:
|
|
45
46
|
input("Press enter to quit")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
import argparse
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
|
|
@@ -65,7 +64,13 @@ def read_args(args: list[str]) -> tuple[argparse.Namespace, list[str]]:
|
|
|
65
64
|
help="The log level",
|
|
66
65
|
)
|
|
67
66
|
|
|
68
|
-
parser.add_argument("--log", type=Path, help="
|
|
67
|
+
parser.add_argument("--log", type=Path, help="path to the log file.")
|
|
68
|
+
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--no-banner",
|
|
71
|
+
action="store_true",
|
|
72
|
+
help="do not print the banner in the console",
|
|
73
|
+
)
|
|
69
74
|
|
|
70
75
|
actions = parser.add_mutually_exclusive_group()
|
|
71
76
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
from collections.abc import Callable
|
|
3
2
|
from contextlib import contextmanager
|
|
4
|
-
import traceback
|
|
5
3
|
from typing import Generator
|
|
6
4
|
|
|
7
5
|
from httpdbg.hooks.utils import getcallargs
|
|
@@ -16,7 +14,7 @@ def set_hook_for_aiohttp_async(records: HTTPRecords, method: Callable):
|
|
|
16
14
|
initiator_and_group = None
|
|
17
15
|
try:
|
|
18
16
|
with httpdbg_initiator(
|
|
19
|
-
records,
|
|
17
|
+
records, method, *args, **kwargs
|
|
20
18
|
) as initiator_and_group:
|
|
21
19
|
ret = await method(*args, **kwargs)
|
|
22
20
|
return ret
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
import builtins
|
|
3
2
|
from collections.abc import Callable
|
|
4
3
|
from contextlib import contextmanager
|
|
5
4
|
import functools
|
|
6
5
|
import importlib
|
|
7
6
|
import inspect
|
|
8
|
-
import traceback
|
|
9
7
|
from types import ModuleType
|
|
10
8
|
from typing import Any
|
|
11
9
|
from typing import Generator
|
|
@@ -22,9 +20,7 @@ def set_hook_for_generic_async(records: HTTPRecords, method: Any):
|
|
|
22
20
|
logger().info(f"SET_HOOK_FOR_GENERIC_ASYNC {method}")
|
|
23
21
|
|
|
24
22
|
async def hook(*args, **kwargs):
|
|
25
|
-
with httpdbg_initiator(
|
|
26
|
-
records, traceback.extract_stack(), method, *args, **kwargs
|
|
27
|
-
):
|
|
23
|
+
with httpdbg_initiator(records, method, *args, **kwargs):
|
|
28
24
|
ret = await method(*args, **kwargs)
|
|
29
25
|
|
|
30
26
|
return ret
|
|
@@ -36,9 +32,7 @@ def set_hook_for_generic(records: HTTPRecords, method: Any):
|
|
|
36
32
|
logger().info(f"SET_HOOK_FOR_GENERIC {method}")
|
|
37
33
|
|
|
38
34
|
def hook(*args, **kwargs):
|
|
39
|
-
with httpdbg_initiator(
|
|
40
|
-
records, traceback.extract_stack(), method, *args, **kwargs
|
|
41
|
-
):
|
|
35
|
+
with httpdbg_initiator(records, method, *args, **kwargs):
|
|
42
36
|
ret = method(*args, **kwargs)
|
|
43
37
|
|
|
44
38
|
return ret
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
import random
|
|
4
|
-
import traceback
|
|
5
4
|
from typing import Generator
|
|
6
5
|
from typing import Union
|
|
7
6
|
|
|
@@ -101,9 +100,7 @@ def set_hook_for_h2_send_headers(records: HTTPRecords, method: Callable):
|
|
|
101
100
|
stream_id = callargs.get("stream_id")
|
|
102
101
|
headers = callargs.get("headers")
|
|
103
102
|
|
|
104
|
-
with httpdbg_initiator(
|
|
105
|
-
records, traceback.extract_stack(), method, *args, **kwargs
|
|
106
|
-
) as initiator_and_group:
|
|
103
|
+
with httpdbg_initiator(records, method, *args, **kwargs) as initiator_and_group:
|
|
107
104
|
initiator, group, _ = initiator_and_group
|
|
108
105
|
if all(x is not None for x in (self, stream_id, headers)):
|
|
109
106
|
logger().debug(
|
|
@@ -127,9 +124,7 @@ def set_hook_for_h2_send_data(records: HTTPRecords, method: Callable):
|
|
|
127
124
|
stream_id = callargs.get("stream_id")
|
|
128
125
|
data = callargs.get("data")
|
|
129
126
|
|
|
130
|
-
with httpdbg_initiator(
|
|
131
|
-
records, traceback.extract_stack(), method, *args, **kwargs
|
|
132
|
-
):
|
|
127
|
+
with httpdbg_initiator(records, method, *args, **kwargs):
|
|
133
128
|
if all(x is not None for x in (self, stream_id, data)):
|
|
134
129
|
logger().debug(
|
|
135
130
|
f"H2 send_data - self={id(self)} steam_id={stream_id} data={data[:20]!r}"
|
|
@@ -146,9 +141,7 @@ def set_hook_for_h2_receive_data(records: HTTPRecords, method: Callable):
|
|
|
146
141
|
callargs = getcallargs(method, *args, **kwargs)
|
|
147
142
|
self = callargs.get("self")
|
|
148
143
|
|
|
149
|
-
with httpdbg_initiator(
|
|
150
|
-
records, traceback.extract_stack(), method, *args, **kwargs
|
|
151
|
-
) as initiator_and_group:
|
|
144
|
+
with httpdbg_initiator(records, method, *args, **kwargs) as initiator_and_group:
|
|
152
145
|
initiator, group, _ = initiator_and_group
|
|
153
146
|
ret = method(*args, **kwargs)
|
|
154
147
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
2
|
from contextlib import contextmanager
|
|
3
|
-
import traceback
|
|
4
3
|
from typing import Generator
|
|
5
4
|
|
|
6
5
|
from httpdbg.hooks.utils import getcallargs
|
|
@@ -15,7 +14,7 @@ def set_hook_for_httpx_async(records: HTTPRecords, method: Callable):
|
|
|
15
14
|
initiator_and_group = None
|
|
16
15
|
try:
|
|
17
16
|
with httpdbg_initiator(
|
|
18
|
-
records,
|
|
17
|
+
records, method, *args, **kwargs
|
|
19
18
|
) as initiator_and_group:
|
|
20
19
|
ret = await method(*args, **kwargs)
|
|
21
20
|
return ret
|
|
@@ -39,7 +38,7 @@ def set_hook_for_httpx(records: HTTPRecords, method: Callable):
|
|
|
39
38
|
initiator_and_group = None
|
|
40
39
|
try:
|
|
41
40
|
with httpdbg_initiator(
|
|
42
|
-
records,
|
|
41
|
+
records, method, *args, **kwargs
|
|
43
42
|
) as initiator_and_group:
|
|
44
43
|
ret = method(*args, **kwargs)
|
|
45
44
|
return ret
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
from collections.abc import Callable
|
|
3
2
|
from contextlib import contextmanager
|
|
4
|
-
import traceback
|
|
5
3
|
from typing import Generator
|
|
6
4
|
|
|
7
5
|
from httpdbg.hooks.utils import getcallargs
|
|
@@ -16,7 +14,7 @@ def set_hook_for_requests(records: HTTPRecords, method: Callable):
|
|
|
16
14
|
initiator_and_group = None
|
|
17
15
|
try:
|
|
18
16
|
with httpdbg_initiator(
|
|
19
|
-
records,
|
|
17
|
+
records, method, *args, **kwargs
|
|
20
18
|
) as initiator_and_group:
|
|
21
19
|
ret = method(*args, **kwargs)
|
|
22
20
|
return ret
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
import asyncio
|
|
3
2
|
import asyncio.proactor_events
|
|
4
3
|
from collections.abc import Callable
|
|
@@ -8,7 +7,6 @@ import platform
|
|
|
8
7
|
import socket
|
|
9
8
|
import ssl
|
|
10
9
|
import sys
|
|
11
|
-
import traceback
|
|
12
10
|
from typing import Generator
|
|
13
11
|
from typing import Union
|
|
14
12
|
|
|
@@ -193,7 +191,7 @@ def set_hook_for_socket_connect(records: HTTPRecords, method: Callable):
|
|
|
193
191
|
): # BlockingIOError for async, OSError for ipv6
|
|
194
192
|
if records.client:
|
|
195
193
|
with httpdbg_initiator(
|
|
196
|
-
records,
|
|
194
|
+
records, method, *args, **kwargs
|
|
197
195
|
) as initiator_and_group:
|
|
198
196
|
initiator, group, is_new = initiator_and_group
|
|
199
197
|
if is_new:
|
|
@@ -221,7 +219,7 @@ def set_hook_for_ssl_wrap_socket(records: HTTPRecords, method: Callable):
|
|
|
221
219
|
except Exception as ex:
|
|
222
220
|
if records.client:
|
|
223
221
|
with httpdbg_initiator(
|
|
224
|
-
records,
|
|
222
|
+
records, method, *args, **kwargs
|
|
225
223
|
) as initiator_and_group:
|
|
226
224
|
initiator, group, is_new = initiator_and_group
|
|
227
225
|
if is_new:
|
|
@@ -256,7 +254,7 @@ def set_hook_for_sslcontext_wrap_socket(records: HTTPRecords, method: Callable):
|
|
|
256
254
|
except Exception as ex:
|
|
257
255
|
if records.client:
|
|
258
256
|
with httpdbg_initiator(
|
|
259
|
-
records,
|
|
257
|
+
records, method, *args, **kwargs
|
|
260
258
|
) as initiator_and_group:
|
|
261
259
|
initiator, group, is_new = initiator_and_group
|
|
262
260
|
if is_new:
|
|
@@ -291,7 +289,7 @@ def set_hook_for_socket_wrap_bio(records: HTTPRecords, method: Callable):
|
|
|
291
289
|
except Exception as ex:
|
|
292
290
|
if records.client:
|
|
293
291
|
with httpdbg_initiator(
|
|
294
|
-
records,
|
|
292
|
+
records, method, *args, **kwargs
|
|
295
293
|
) as initiator_and_group:
|
|
296
294
|
initiator, group, is_new = initiator_and_group
|
|
297
295
|
if is_new:
|
|
@@ -345,7 +343,6 @@ def set_hook_for_socket_recv_into(records: HTTPRecords, method: Callable):
|
|
|
345
343
|
)
|
|
346
344
|
with httpdbg_initiator(
|
|
347
345
|
records,
|
|
348
|
-
traceback.extract_stack(),
|
|
349
346
|
method,
|
|
350
347
|
self,
|
|
351
348
|
buffer,
|
|
@@ -404,7 +401,6 @@ def set_hook_for_socket_recv(records: HTTPRecords, method: Callable):
|
|
|
404
401
|
logger().info("RECV - http detected")
|
|
405
402
|
with httpdbg_initiator(
|
|
406
403
|
records,
|
|
407
|
-
traceback.extract_stack(),
|
|
408
404
|
method,
|
|
409
405
|
self,
|
|
410
406
|
bufsize,
|
|
@@ -459,7 +455,6 @@ def set_hook_for_socket_sendall(records: HTTPRecords, method: Callable):
|
|
|
459
455
|
logger().info("SENDALL - http detected")
|
|
460
456
|
with httpdbg_initiator(
|
|
461
457
|
records,
|
|
462
|
-
traceback.extract_stack(),
|
|
463
458
|
method,
|
|
464
459
|
self,
|
|
465
460
|
data,
|
|
@@ -515,7 +510,6 @@ def set_hook_for_socket_send(records: HTTPRecords, method: Callable):
|
|
|
515
510
|
if http_detected:
|
|
516
511
|
with httpdbg_initiator(
|
|
517
512
|
records,
|
|
518
|
-
traceback.extract_stack(),
|
|
519
513
|
method,
|
|
520
514
|
self,
|
|
521
515
|
data,
|
|
@@ -595,7 +589,6 @@ def set_hook_for_sslobject_write(records: HTTPRecords, method: Callable):
|
|
|
595
589
|
if http_detected:
|
|
596
590
|
with httpdbg_initiator(
|
|
597
591
|
records,
|
|
598
|
-
traceback.extract_stack(),
|
|
599
592
|
method,
|
|
600
593
|
self,
|
|
601
594
|
buf,
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
from collections.abc import Callable
|
|
3
2
|
from contextlib import contextmanager
|
|
4
|
-
import traceback
|
|
5
3
|
from typing import Generator
|
|
6
4
|
|
|
7
5
|
from httpdbg.hooks.utils import getcallargs
|
|
@@ -16,7 +14,7 @@ def set_hook_for_urllib3(records: HTTPRecords, method: Callable):
|
|
|
16
14
|
initiator_and_group = None
|
|
17
15
|
try:
|
|
18
16
|
with httpdbg_initiator(
|
|
19
|
-
records,
|
|
17
|
+
records, method, *args, **kwargs
|
|
20
18
|
) as initiator_and_group:
|
|
21
19
|
ret = method(*args, **kwargs)
|
|
22
20
|
return ret
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
from collections.abc import Callable
|
|
3
2
|
from contextlib import contextmanager
|
|
4
3
|
import datetime
|
|
5
|
-
import traceback
|
|
6
4
|
import typing
|
|
7
5
|
from typing import Generator
|
|
8
6
|
|
|
@@ -66,7 +64,6 @@ def set_hook_uvicorn_data_received(records: HTTPRecords, method: Callable):
|
|
|
66
64
|
logger().info("UVICORN - http detected")
|
|
67
65
|
with httpdbg_initiator(
|
|
68
66
|
records,
|
|
69
|
-
traceback.extract_stack(),
|
|
70
67
|
method,
|
|
71
68
|
self,
|
|
72
69
|
data,
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from contextlib import contextmanager
|
|
4
4
|
import datetime
|
|
5
|
+
import functools
|
|
5
6
|
import inspect
|
|
7
|
+
import linecache
|
|
6
8
|
import os
|
|
7
9
|
import platform
|
|
8
10
|
import traceback
|
|
@@ -98,33 +100,27 @@ def in_lib(line: str, packages: list[str] = None):
|
|
|
98
100
|
def get_current_instruction(
|
|
99
101
|
extracted_stack: traceback.StackSummary,
|
|
100
102
|
) -> tuple[str, str, list[str]]:
|
|
101
|
-
instruction = ""
|
|
102
|
-
short_stack = ""
|
|
103
|
-
stack = []
|
|
103
|
+
instruction: str = ""
|
|
104
|
+
short_stack: str = ""
|
|
105
|
+
stack: list[str] = []
|
|
104
106
|
|
|
105
107
|
try:
|
|
106
|
-
n_stack = -
|
|
107
|
-
framesummary = extracted_stack[-
|
|
108
|
-
while "asyncio" in framesummary.filename:
|
|
109
|
-
n_stack -= 1
|
|
110
|
-
framesummary = extracted_stack[n_stack - 1]
|
|
108
|
+
n_stack = -2
|
|
109
|
+
framesummary = extracted_stack[-3]
|
|
111
110
|
|
|
112
|
-
while (
|
|
113
|
-
"httpdbg
|
|
111
|
+
while (
|
|
112
|
+
("httpdbg/hooks" in framesummary.filename)
|
|
113
|
+
or ("httpdbg\\hooks" in framesummary.filename)
|
|
114
|
+
or ("asyncio" in framesummary.filename)
|
|
114
115
|
):
|
|
115
116
|
n_stack -= 1
|
|
116
117
|
framesummary = extracted_stack[n_stack - 1]
|
|
117
118
|
|
|
118
|
-
short_stack = f'File "{framesummary.filename}", line {framesummary.lineno}, in {framesummary.name}\n'
|
|
119
119
|
if os.path.exists(framesummary.filename) and framesummary.lineno is not None:
|
|
120
|
-
instruction, s_stack = extract_short_stack_from_file(
|
|
121
|
-
framesummary.filename, framesummary.lineno, 0, 8
|
|
122
|
-
)
|
|
123
|
-
short_stack += s_stack
|
|
124
120
|
|
|
125
121
|
# stack
|
|
126
122
|
to_include = False
|
|
127
|
-
for i_stack in range(
|
|
123
|
+
for i_stack in range(7, len(extracted_stack) + n_stack):
|
|
128
124
|
last_stack = i_stack == len(extracted_stack) + n_stack - 1
|
|
129
125
|
fs = extracted_stack[i_stack]
|
|
130
126
|
to_include = to_include or (
|
|
@@ -132,14 +128,20 @@ def get_current_instruction(
|
|
|
132
128
|
and ("importlib" not in fs.filename)
|
|
133
129
|
) # remove the stack before to start the user part
|
|
134
130
|
if to_include:
|
|
135
|
-
|
|
131
|
+
instruction, s_stack, l_stack = extract_short_stack_from_file(
|
|
136
132
|
fs.filename,
|
|
137
133
|
fs.lineno if fs.lineno else 0,
|
|
138
|
-
4 if last_stack else 0,
|
|
139
|
-
8,
|
|
140
134
|
not last_stack,
|
|
141
135
|
)
|
|
142
|
-
|
|
136
|
+
if last_stack:
|
|
137
|
+
short_stack = (
|
|
138
|
+
f'File "{fs.filename}", line {fs.lineno}, in {fs.name}\n'
|
|
139
|
+
)
|
|
140
|
+
short_stack += s_stack
|
|
141
|
+
|
|
142
|
+
stack.append(
|
|
143
|
+
f'File "{fs.filename}", line {fs.lineno}, \n{l_stack}\n'
|
|
144
|
+
)
|
|
143
145
|
|
|
144
146
|
else:
|
|
145
147
|
instruction = framesummary.line if framesummary.line else "console"
|
|
@@ -153,52 +155,57 @@ def get_current_instruction(
|
|
|
153
155
|
return instruction.replace("\n", " "), short_stack, stack
|
|
154
156
|
|
|
155
157
|
|
|
158
|
+
@functools.cache
|
|
156
159
|
def extract_short_stack_from_file(
|
|
157
160
|
filename: str,
|
|
158
161
|
lineno: int,
|
|
159
|
-
before: int,
|
|
160
|
-
after: int,
|
|
161
162
|
stop_if_instruction_ends: bool = True,
|
|
162
|
-
) -> tuple[str, str]:
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
) -> tuple[str, str, str]:
|
|
164
|
+
before: int = 4
|
|
165
|
+
after: int = 8
|
|
166
|
+
instruction: str = ""
|
|
167
|
+
short_stack: str = ""
|
|
168
|
+
long_stack: str = ""
|
|
165
169
|
|
|
166
170
|
try:
|
|
167
171
|
if os.path.exists(filename):
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if end_of_instruction_found and stop_if_instruction_ends:
|
|
172
|
+
# copy the lines before, only for the "long" stack (if they are not empty)
|
|
173
|
+
copyit = False
|
|
174
|
+
for i in range(max(0, lineno - before), lineno):
|
|
175
|
+
line = linecache.getline(filename, i).removesuffix("\n").rstrip()
|
|
176
|
+
copyit = copyit or (line != "")
|
|
177
|
+
if copyit:
|
|
178
|
+
long_stack += f" {i}. {line}\n"
|
|
179
|
+
|
|
180
|
+
# try to recompose the instruction if on multi-lines
|
|
181
|
+
end_of_instruction_found = False
|
|
182
|
+
for i in range(max(0, lineno), lineno + after):
|
|
183
|
+
line = linecache.getline(filename, i).removesuffix("\n").rstrip()
|
|
184
|
+
if not end_of_instruction_found:
|
|
185
|
+
instruction += line.strip()
|
|
186
|
+
short_stack += f" {i}. {line}\n"
|
|
187
|
+
long_stack += (
|
|
188
|
+
f" {i}. {line}{' <====' if (before > 0 and i == lineno) else ''}\n"
|
|
189
|
+
)
|
|
190
|
+
nb_parenthesis = 0
|
|
191
|
+
for c in instruction[instruction.find("(") :]:
|
|
192
|
+
if c == "(":
|
|
193
|
+
nb_parenthesis += 1
|
|
194
|
+
if c == ")":
|
|
195
|
+
nb_parenthesis -= 1
|
|
196
|
+
if nb_parenthesis == 0:
|
|
197
|
+
end_of_instruction_found = True
|
|
195
198
|
break
|
|
199
|
+
if end_of_instruction_found and stop_if_instruction_ends:
|
|
200
|
+
break
|
|
196
201
|
except Exception as ex:
|
|
202
|
+
tb = traceback.extract_tb(ex.__traceback__)
|
|
203
|
+
_, lineno, _, _ = tb[-1]
|
|
197
204
|
logger().info(
|
|
198
|
-
f"EXTRACT_SHORT_STACK_FROM_FILE {filename} lineno={lineno} before={before} after={after}- error - {str(ex)}"
|
|
205
|
+
f"EXTRACT_SHORT_STACK_FROM_FILE {filename} lineno={lineno} before={before} after={after}- error (line {lineno}) - {str(ex)}",
|
|
199
206
|
)
|
|
200
207
|
|
|
201
|
-
return instruction, short_stack
|
|
208
|
+
return instruction, short_stack, long_stack
|
|
202
209
|
|
|
203
210
|
|
|
204
211
|
def construct_call_str(original_method, *args, **kwargs):
|
|
@@ -237,16 +244,16 @@ def construct_call_str(original_method, *args, **kwargs):
|
|
|
237
244
|
@contextmanager
|
|
238
245
|
def httpdbg_initiator(
|
|
239
246
|
records: "HTTPRecords",
|
|
240
|
-
extracted_stack: traceback.StackSummary,
|
|
241
247
|
original_method: Callable,
|
|
242
248
|
*args,
|
|
243
249
|
**kwargs,
|
|
244
250
|
) -> Generator[tuple[Initiator, Group, bool], None, None]:
|
|
245
|
-
|
|
246
251
|
try:
|
|
247
252
|
if records.current_initiator is None:
|
|
248
253
|
initiator_already_set = False
|
|
249
254
|
|
|
255
|
+
extracted_stack: traceback.StackSummary = traceback.extract_stack()
|
|
256
|
+
|
|
250
257
|
# temporary set a fake initiator env variable to avoid a recursion error
|
|
251
258
|
# RecursionError: maximum recursion depth exceeded while calling a Python object
|
|
252
259
|
# TL;DR When we construct the short_stack string, a recursion error occurs if there
|
|
@@ -346,7 +353,7 @@ def httpdbg_endpoint(
|
|
|
346
353
|
filename = inspect.getsourcefile(original_method)
|
|
347
354
|
if filename:
|
|
348
355
|
_, lineno = inspect.getsourcelines(original_method)
|
|
349
|
-
instruction, s_stack = extract_short_stack_from_file(filename, lineno
|
|
356
|
+
instruction, s_stack, _ = extract_short_stack_from_file(filename, lineno)
|
|
350
357
|
full_label = (
|
|
351
358
|
f'File "{filename}", line {lineno}, in {original_method.__name__}\n'
|
|
352
359
|
)
|
|
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.0.0 → httpdbg-2.0.2}/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
|
{httpdbg-2.0.0 → httpdbg-2.0.2}/httpdbg/webapp/static/icons/information-mark-circle-outline-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-2.0.0 → httpdbg-2.0.2}/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
|
|
File without changes
|