httpdbg 0.7.1__tar.gz → 0.7.3__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-0.7.1 → httpdbg-0.7.3}/PKG-INFO +3 -3
- {httpdbg-0.7.1 → httpdbg-0.7.3}/README.md +2 -2
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/__init__.py +1 -1
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/socket.py +26 -20
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/records.py +26 -11
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg.egg-info/PKG-INFO +3 -3
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_hook_aiohttp.py +27 -1
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_hook_httpx.py +67 -15
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_hook_requests.py +41 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/LICENSE +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/__main__.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/args.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/__init__.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/aiohttp.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/all.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/httpx.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/requests.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/urllib3.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/hooks/utils.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/initiator.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/mode_console.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/mode_module.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/mode_script.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/server.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/utils.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/__init__.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/api.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/app.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/preview.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/api.js +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/column.css +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/configuration.js +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/detail.css +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/favicon.ico +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/filter.js +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/index.htm +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/main.js +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/mustache.min.js +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/render.js +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/style.css +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/table.css +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg/webapp/static/tooltip.css +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg.egg-info/SOURCES.txt +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg.egg-info/dependency_links.txt +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg.egg-info/entry_points.txt +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/httpdbg.egg-info/top_level.txt +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/pyproject.toml +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/setup.cfg +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_api.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_cli.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_context_manager.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_hook_urllib3.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_mode_console.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_mode_module_pytest.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_mode_script.py +0 -0
- {httpdbg-0.7.1 → httpdbg-0.7.3}/tests/test_preview.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: httpdbg
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: A very simple tool to debug HTTP(S) client requests
|
|
5
5
|
Author-email: cle-b <cle@tictac.pm>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -86,8 +86,8 @@ pyhttpdbg -m pip install httpdbg --upgrade
|
|
|
86
86
|
|------------|-------------|-------------------------------------------------------------------|
|
|
87
87
|
| requests | supported | - |
|
|
88
88
|
| urllib3 | supported | - |
|
|
89
|
-
| httpx | supported | Async
|
|
90
|
-
| aiohttp | supported | HTTP requests not intercepted on Windows
|
|
89
|
+
| httpx | supported | Async HTTP requests not intercepted on Windows (HTTPS OK) |
|
|
90
|
+
| aiohttp | supported | Async HTTP requests not intercepted on Windows (HTTPS OK) |
|
|
91
91
|
|
|
92
92
|
## configuration
|
|
93
93
|
|
|
@@ -66,8 +66,8 @@ pyhttpdbg -m pip install httpdbg --upgrade
|
|
|
66
66
|
|------------|-------------|-------------------------------------------------------------------|
|
|
67
67
|
| requests | supported | - |
|
|
68
68
|
| urllib3 | supported | - |
|
|
69
|
-
| httpx | supported | Async
|
|
70
|
-
| aiohttp | supported | HTTP requests not intercepted on Windows
|
|
69
|
+
| httpx | supported | Async HTTP requests not intercepted on Windows (HTTPS OK) |
|
|
70
|
+
| aiohttp | supported | Async HTTP requests not intercepted on Windows (HTTPS OK) |
|
|
71
71
|
|
|
72
72
|
## configuration
|
|
73
73
|
|
|
@@ -32,7 +32,9 @@ def set_hook_for_socket_connect(records, method):
|
|
|
32
32
|
try:
|
|
33
33
|
r = method(self, address)
|
|
34
34
|
except Exception as ex:
|
|
35
|
-
if not isinstance(
|
|
35
|
+
if not isinstance(
|
|
36
|
+
ex, (BlockingIOError, OSError)
|
|
37
|
+
): # BlockingIOError for async, OSError for ipv6
|
|
36
38
|
record = HTTPRecord()
|
|
37
39
|
record.initiator = get_initiator(records._initiators)
|
|
38
40
|
|
|
@@ -61,11 +63,13 @@ def set_hook_for_ssl_wrap_socket(records, method):
|
|
|
61
63
|
|
|
62
64
|
raise
|
|
63
65
|
|
|
66
|
+
logger.info(
|
|
67
|
+
f"WRAP_SOCKET - {type(sock)}={id(sock)} {type(sslsocket)}={id(sslsocket)}"
|
|
68
|
+
)
|
|
69
|
+
|
|
64
70
|
socketdata = records.move_socket_data(sslsocket, sock)
|
|
65
71
|
if socketdata:
|
|
66
|
-
logger.info(
|
|
67
|
-
f"WRAP_SOCKET - sock={sock} sockid={id(sock)} sslsocket={sslsocket} sslsocketid={id(sslsocket)} socketdata={socketdata}"
|
|
68
|
-
)
|
|
72
|
+
logger.info(f"WRAP_SOCKET * - socketdata={socketdata}")
|
|
69
73
|
|
|
70
74
|
return sslsocket
|
|
71
75
|
|
|
@@ -86,11 +90,13 @@ def set_hook_for_sslcontext_wrap_socket(records, method):
|
|
|
86
90
|
|
|
87
91
|
raise
|
|
88
92
|
|
|
93
|
+
logger.info(
|
|
94
|
+
f"WRAP_SOCKET (SSLContext) - {type(self)}={id(self)} {type(sock)}={id(sock)} {type(sslsocket)}={id(sslsocket)}"
|
|
95
|
+
)
|
|
96
|
+
|
|
89
97
|
socketdata = records.move_socket_data(sslsocket, sock)
|
|
90
98
|
if socketdata:
|
|
91
|
-
logger.info(
|
|
92
|
-
f"WRAP_SOCKET (SSLContext) - socket={sock} socketid={id(sock)} sslsocket={sslsocket} sslsocketid={id(sslsocket)} socketdata={socketdata}"
|
|
93
|
-
)
|
|
99
|
+
logger.info(f"WRAP_SOCKET (SSLContext) * - socketdata={socketdata}")
|
|
94
100
|
|
|
95
101
|
return sslsocket
|
|
96
102
|
|
|
@@ -111,11 +117,13 @@ def set_hook_for_socket_wrap_bio(records, method):
|
|
|
111
117
|
|
|
112
118
|
raise
|
|
113
119
|
|
|
114
|
-
|
|
120
|
+
logger.info(
|
|
121
|
+
f"WRAP_SOCKET_BIO - {type(self)}={id(self)} {type(sslobject)}={id(sslobject)}"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
socketdata = records.get_socket_data(sslobject, self)
|
|
115
125
|
if socketdata:
|
|
116
|
-
logger.info(
|
|
117
|
-
f"WRAP_SOCKET_BIO - sock={self} sockid={id(self)} sslobject={sslobject} sslobjectid={id(sslobject)} socketdata={socketdata}"
|
|
118
|
-
)
|
|
126
|
+
logger.info(f"WRAP_SOCKET_BIO * - socketdata={socketdata}")
|
|
119
127
|
|
|
120
128
|
return sslobject
|
|
121
129
|
|
|
@@ -171,7 +179,7 @@ def set_hook_for_socket_recv(records, method):
|
|
|
171
179
|
|
|
172
180
|
def set_hook_for_socket_sendall(records, method):
|
|
173
181
|
def hook(self, bytes, *args, **kwargs):
|
|
174
|
-
socketdata = records.get_socket_data(self)
|
|
182
|
+
socketdata = records.get_socket_data(self, request=True)
|
|
175
183
|
if socketdata:
|
|
176
184
|
logger.info(
|
|
177
185
|
f"SENDALL - self={self} id={id(self)} socketdata={socketdata} bytes={(b''+bytes)[:20]} type={type(bytes)} len={len(bytes)} args={args} kwargs={kwargs}"
|
|
@@ -206,7 +214,7 @@ def set_hook_for_socket_sendall(records, method):
|
|
|
206
214
|
|
|
207
215
|
def set_hook_for_socket_send(records, method):
|
|
208
216
|
def hook(self, bytes, *args, **kwargs):
|
|
209
|
-
socketdata = records.get_socket_data(self)
|
|
217
|
+
socketdata = records.get_socket_data(self, request=True)
|
|
210
218
|
if socketdata:
|
|
211
219
|
logger.info(
|
|
212
220
|
f"SEND - self={self} id={id(self)} socketdata={socketdata} bytes={(b''+bytes)[:20]} args={args} kwargs={kwargs}"
|
|
@@ -264,11 +272,10 @@ def set_hook_for_asyncio_create_connection(records, method):
|
|
|
264
272
|
|
|
265
273
|
def set_hook_for_sslobject_write(records, method):
|
|
266
274
|
def hook(self, buf, *args, **kwargs):
|
|
267
|
-
|
|
275
|
+
logger.info(f"WRITE - {type(self)}={id(self)} buf={(b'' + buf)[:20]}")
|
|
276
|
+
socketdata = records.get_socket_data(self, request=True)
|
|
268
277
|
if socketdata:
|
|
269
|
-
logger.info(
|
|
270
|
-
f"WRITE - self={self} id={id(self)} socketdata={socketdata} buf={(b'' + buf)[:20]} args={args} kwargs={kwargs}"
|
|
271
|
-
)
|
|
278
|
+
logger.info(f"WRITE * - socketdata={socketdata}")
|
|
272
279
|
|
|
273
280
|
try:
|
|
274
281
|
size = method(self, buf, *args, **kwargs)
|
|
@@ -299,11 +306,10 @@ def set_hook_for_sslobject_write(records, method):
|
|
|
299
306
|
|
|
300
307
|
def set_hook_for_sslobject_read(records, method):
|
|
301
308
|
def hook(self, *args, **kwargs):
|
|
309
|
+
logger.info(f"READ - {type(self)}={id(self)}")
|
|
302
310
|
socketdata = records.get_socket_data(self)
|
|
303
311
|
if socketdata:
|
|
304
|
-
logger.info(
|
|
305
|
-
f"READ - self={self} id={id(self)} socketdata={socketdata} args={args} kwargs={kwargs}"
|
|
306
|
-
)
|
|
312
|
+
logger.info(f"READ * - socketdata={socketdata}")
|
|
307
313
|
|
|
308
314
|
try:
|
|
309
315
|
r = method(self, *args, **kwargs)
|
|
@@ -64,14 +64,25 @@ class HTTPRecords:
|
|
|
64
64
|
def __len__(self):
|
|
65
65
|
return len(self.requests)
|
|
66
66
|
|
|
67
|
-
def get_socket_data(self, obj, extra_sock=None, force_new=False):
|
|
68
|
-
|
|
67
|
+
def get_socket_data(self, obj, extra_sock=None, force_new=False, request=None):
|
|
68
|
+
socketdata = None
|
|
69
69
|
|
|
70
70
|
if force_new:
|
|
71
71
|
self.del_socket_data(obj)
|
|
72
72
|
|
|
73
73
|
if id(obj) in self._sockets:
|
|
74
|
-
|
|
74
|
+
socketdata = self._sockets[id(obj)]
|
|
75
|
+
if request:
|
|
76
|
+
if (
|
|
77
|
+
socketdata
|
|
78
|
+
and socketdata.record
|
|
79
|
+
and socketdata.record.response.rawdata
|
|
80
|
+
):
|
|
81
|
+
# the socket is reused for a new request
|
|
82
|
+
self._sockets[id(obj)] = SocketRawData(
|
|
83
|
+
id(obj), socketdata.address, socketdata.ssl
|
|
84
|
+
)
|
|
85
|
+
socketdata = self._sockets[id(obj)]
|
|
75
86
|
else:
|
|
76
87
|
if isinstance(obj, socket.socket):
|
|
77
88
|
try:
|
|
@@ -79,33 +90,37 @@ class HTTPRecords:
|
|
|
79
90
|
self._sockets[id(obj)] = SocketRawData(
|
|
80
91
|
id(obj), address, isinstance(obj, ssl.SSLSocket)
|
|
81
92
|
)
|
|
82
|
-
|
|
93
|
+
socketdata = self._sockets[id(obj)]
|
|
83
94
|
except OSError:
|
|
84
95
|
# OSError: [WinError 10022] An invalid argument was supplied
|
|
85
96
|
pass
|
|
86
97
|
else:
|
|
87
98
|
if extra_sock:
|
|
88
99
|
try:
|
|
89
|
-
address =
|
|
100
|
+
address = (
|
|
101
|
+
extra_sock.getsockname()
|
|
102
|
+
if hasattr(extra_sock, "getsockname")
|
|
103
|
+
else ("", 0) # wrap_bio
|
|
104
|
+
)
|
|
90
105
|
self._sockets[id(obj)] = SocketRawData(
|
|
91
106
|
id(obj),
|
|
92
107
|
address,
|
|
93
108
|
isinstance(obj, (ssl.SSLObject, ssl.SSLSocket)),
|
|
94
109
|
)
|
|
95
|
-
|
|
110
|
+
socketdata = self._sockets[id(obj)]
|
|
96
111
|
except OSError:
|
|
97
112
|
# OSError: [WinError 10022] An invalid argument was supplied
|
|
98
113
|
pass
|
|
99
114
|
|
|
100
|
-
return
|
|
115
|
+
return socketdata
|
|
101
116
|
|
|
102
117
|
def move_socket_data(self, dest, ori):
|
|
103
118
|
if id(ori) in self._sockets:
|
|
104
|
-
|
|
105
|
-
if
|
|
106
|
-
self._sockets[id(dest)] =
|
|
119
|
+
socketdata = self.get_socket_data(ori)
|
|
120
|
+
if socketdata:
|
|
121
|
+
self._sockets[id(dest)] = socketdata
|
|
107
122
|
if isinstance(dest, (ssl.SSLSocket, ssl.SSLObject)):
|
|
108
|
-
|
|
123
|
+
socketdata.ssl = True
|
|
109
124
|
self.del_socket_data(ori)
|
|
110
125
|
|
|
111
126
|
def del_socket_data(self, obj):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: httpdbg
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: A very simple tool to debug HTTP(S) client requests
|
|
5
5
|
Author-email: cle-b <cle@tictac.pm>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -86,8 +86,8 @@ pyhttpdbg -m pip install httpdbg --upgrade
|
|
|
86
86
|
|------------|-------------|-------------------------------------------------------------------|
|
|
87
87
|
| requests | supported | - |
|
|
88
88
|
| urllib3 | supported | - |
|
|
89
|
-
| httpx | supported | Async
|
|
90
|
-
| aiohttp | supported | HTTP requests not intercepted on Windows
|
|
89
|
+
| httpx | supported | Async HTTP requests not intercepted on Windows (HTTPS OK) |
|
|
90
|
+
| aiohttp | supported | Async HTTP requests not intercepted on Windows (HTTPS OK) |
|
|
91
91
|
|
|
92
92
|
## configuration
|
|
93
93
|
|
|
@@ -321,7 +321,7 @@ async def test_aiohttp_exception_asyncclient():
|
|
|
321
321
|
platform.system().lower() == "windows",
|
|
322
322
|
reason="Async HTTP requests not intercepted on Windows",
|
|
323
323
|
)
|
|
324
|
-
async def
|
|
324
|
+
async def test_aiohttp_get_empty_request_content_asyncclient(httpbin_both):
|
|
325
325
|
with httpdbg() as records:
|
|
326
326
|
async with aiohttp.ClientSession(
|
|
327
327
|
connector=aiohttp.TCPConnector(verify_ssl=False)
|
|
@@ -333,3 +333,29 @@ async def test_aiohttp_get_empty_request_content(httpbin_both):
|
|
|
333
333
|
|
|
334
334
|
assert http_record.url == f"{httpbin_both.url}/get"
|
|
335
335
|
assert http_record.request.content == b""
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
@pytest.mark.aiohttp
|
|
339
|
+
@pytest.mark.asyncio
|
|
340
|
+
@pytest.mark.xfail(
|
|
341
|
+
platform.system().lower() == "windows",
|
|
342
|
+
reason="Async HTTP requests not intercepted on Windows",
|
|
343
|
+
)
|
|
344
|
+
async def test_aiohttp_many_requests_session_asyncclient():
|
|
345
|
+
with httpdbg() as records:
|
|
346
|
+
async with aiohttp.ClientSession() as session:
|
|
347
|
+
await session.get("https://httpbin.org/get")
|
|
348
|
+
await session.get("https://httpbin.org/get/abc")
|
|
349
|
+
await session.post("https://httpbin.org/post", data="abc")
|
|
350
|
+
await session.get("https://httpbin.org/get")
|
|
351
|
+
|
|
352
|
+
assert len(records) == 4
|
|
353
|
+
|
|
354
|
+
assert records[0].url == "https://httpbin.org/get"
|
|
355
|
+
assert records[0].request.content == b""
|
|
356
|
+
assert records[1].url == "https://httpbin.org/get/abc"
|
|
357
|
+
assert records[1].request.content == b""
|
|
358
|
+
assert records[2].url == "https://httpbin.org/post"
|
|
359
|
+
assert records[2].request.content == b"abc"
|
|
360
|
+
assert records[3].url == "https://httpbin.org/get"
|
|
361
|
+
assert records[3].request.content == b""
|
|
@@ -232,15 +232,53 @@ def test_httpx_get_empty_request_content(httpbin_both):
|
|
|
232
232
|
assert http_record.request.content == b""
|
|
233
233
|
|
|
234
234
|
|
|
235
|
+
@pytest.mark.httpx
|
|
236
|
+
def test_httpx_many_requests():
|
|
237
|
+
with httpdbg() as records:
|
|
238
|
+
httpx.get("https://httpbin.org/get")
|
|
239
|
+
httpx.get("https://httpbin.org/get/abc")
|
|
240
|
+
httpx.post("https://httpbin.org/post", data="abc")
|
|
241
|
+
httpx.get("https://httpbin.org/get")
|
|
242
|
+
|
|
243
|
+
assert len(records) == 4
|
|
244
|
+
|
|
245
|
+
assert records[0].url == "https://httpbin.org/get"
|
|
246
|
+
assert records[0].request.content == b""
|
|
247
|
+
assert records[1].url == "https://httpbin.org/get/abc"
|
|
248
|
+
assert records[1].request.content == b""
|
|
249
|
+
assert records[2].url == "https://httpbin.org/post"
|
|
250
|
+
assert records[2].request.content == b"abc"
|
|
251
|
+
assert records[3].url == "https://httpbin.org/get"
|
|
252
|
+
assert records[3].request.content == b""
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
@pytest.mark.httpx
|
|
256
|
+
def test_httpx_many_requests_session():
|
|
257
|
+
with httpdbg() as records:
|
|
258
|
+
with httpx.Client() as session:
|
|
259
|
+
session.get("https://httpbin.org/get")
|
|
260
|
+
session.get("https://httpbin.org/get/abc")
|
|
261
|
+
session.post("https://httpbin.org/post", data="abc")
|
|
262
|
+
session.get("https://httpbin.org/get")
|
|
263
|
+
|
|
264
|
+
assert len(records) == 4
|
|
265
|
+
|
|
266
|
+
assert records[0].url == "https://httpbin.org/get"
|
|
267
|
+
assert records[0].request.content == b""
|
|
268
|
+
assert records[1].url == "https://httpbin.org/get/abc"
|
|
269
|
+
assert records[1].request.content == b""
|
|
270
|
+
assert records[2].url == "https://httpbin.org/post"
|
|
271
|
+
assert records[2].request.content == b"abc"
|
|
272
|
+
assert records[3].url == "https://httpbin.org/get"
|
|
273
|
+
assert records[3].request.content == b""
|
|
274
|
+
|
|
275
|
+
|
|
235
276
|
@pytest.mark.httpx
|
|
236
277
|
@pytest.mark.asyncio
|
|
237
278
|
@pytest.mark.xfail(
|
|
238
279
|
platform.system().lower() == "windows",
|
|
239
280
|
reason="Async HTTP requests not intercepted on Windows",
|
|
240
281
|
)
|
|
241
|
-
@pytest.mark.xfail(
|
|
242
|
-
reason="Async HTTPS requests not intercepted",
|
|
243
|
-
)
|
|
244
282
|
async def test_httpx_asyncclient(httpbin_both):
|
|
245
283
|
with httpdbg() as records:
|
|
246
284
|
async with httpx.AsyncClient(verify=False) as client:
|
|
@@ -285,9 +323,6 @@ async def test_httpx_initiator_asyncclient(httpbin):
|
|
|
285
323
|
platform.system().lower() == "windows",
|
|
286
324
|
reason="Async HTTP requests not intercepted on Windows",
|
|
287
325
|
)
|
|
288
|
-
@pytest.mark.xfail(
|
|
289
|
-
reason="Async HTTPS requests not intercepted",
|
|
290
|
-
)
|
|
291
326
|
async def test_httpx_request_asyncclient(httpbin_both):
|
|
292
327
|
with httpdbg() as records:
|
|
293
328
|
async with httpx.AsyncClient(verify=False) as client:
|
|
@@ -310,9 +345,6 @@ async def test_httpx_request_asyncclient(httpbin_both):
|
|
|
310
345
|
platform.system().lower() == "windows",
|
|
311
346
|
reason="Async HTTP requests not intercepted on Windows",
|
|
312
347
|
)
|
|
313
|
-
@pytest.mark.xfail(
|
|
314
|
-
reason="Async HTTPS requests not intercepted",
|
|
315
|
-
)
|
|
316
348
|
async def test_httpx_response_asyncclient(httpbin_both):
|
|
317
349
|
with httpdbg() as records:
|
|
318
350
|
async with httpx.AsyncClient(verify=False) as client:
|
|
@@ -370,9 +402,6 @@ async def test_httpx_cookies_asyncclient(httpbin):
|
|
|
370
402
|
platform.system().lower() == "windows",
|
|
371
403
|
reason="Async HTTP requests not intercepted on Windows",
|
|
372
404
|
)
|
|
373
|
-
@pytest.mark.xfail(
|
|
374
|
-
reason="Async HTTPS requests not intercepted",
|
|
375
|
-
)
|
|
376
405
|
async def test_httpx_cookies_asyncclient_secure(httpbin_secure):
|
|
377
406
|
with httpdbg() as records:
|
|
378
407
|
async with httpx.AsyncClient(verify=False) as client:
|
|
@@ -426,9 +455,6 @@ async def test_httpx_exception_asyncclient():
|
|
|
426
455
|
platform.system().lower() == "windows",
|
|
427
456
|
reason="Async HTTP requests not intercepted on Windows",
|
|
428
457
|
)
|
|
429
|
-
@pytest.mark.xfail(
|
|
430
|
-
reason="Async HTTPS requests not intercepted",
|
|
431
|
-
)
|
|
432
458
|
async def test_httpx_get_empty_request_content_asyncclient(httpbin_both):
|
|
433
459
|
with httpdbg() as records:
|
|
434
460
|
async with httpx.AsyncClient(verify=False) as client:
|
|
@@ -439,3 +465,29 @@ async def test_httpx_get_empty_request_content_asyncclient(httpbin_both):
|
|
|
439
465
|
|
|
440
466
|
assert http_record.url == f"{httpbin_both.url}/get"
|
|
441
467
|
assert http_record.request.content == b""
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
@pytest.mark.httpx
|
|
471
|
+
@pytest.mark.asyncio
|
|
472
|
+
@pytest.mark.xfail(
|
|
473
|
+
platform.system().lower() == "windows",
|
|
474
|
+
reason="Async HTTP requests not intercepted on Windows",
|
|
475
|
+
)
|
|
476
|
+
async def test_httpx_many_requests_session_asyncclient():
|
|
477
|
+
with httpdbg() as records:
|
|
478
|
+
async with httpx.AsyncClient() as session:
|
|
479
|
+
await session.get("https://httpbin.org/get")
|
|
480
|
+
await session.get("https://httpbin.org/get/abc")
|
|
481
|
+
await session.post("https://httpbin.org/post", data="abc")
|
|
482
|
+
await session.get("https://httpbin.org/get")
|
|
483
|
+
|
|
484
|
+
assert len(records) == 4
|
|
485
|
+
|
|
486
|
+
assert records[0].url == "https://httpbin.org/get"
|
|
487
|
+
assert records[0].request.content == b""
|
|
488
|
+
assert records[1].url == "https://httpbin.org/get/abc"
|
|
489
|
+
assert records[1].request.content == b""
|
|
490
|
+
assert records[2].url == "https://httpbin.org/post"
|
|
491
|
+
assert records[2].request.content == b"abc"
|
|
492
|
+
assert records[3].url == "https://httpbin.org/get"
|
|
493
|
+
assert records[3].request.content == b""
|
|
@@ -217,3 +217,44 @@ def test_requests_get_empty_request_content(httpbin_both):
|
|
|
217
217
|
|
|
218
218
|
assert http_record.url == f"{httpbin_both.url}/get"
|
|
219
219
|
assert http_record.request.content == b""
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@pytest.mark.requests
|
|
223
|
+
def test_requests_many_requests():
|
|
224
|
+
with httpdbg() as records:
|
|
225
|
+
requests.get("https://httpbin.org/get")
|
|
226
|
+
requests.get("https://httpbin.org/get/abc")
|
|
227
|
+
requests.post("https://httpbin.org/post", data="abc")
|
|
228
|
+
requests.get("https://httpbin.org/get")
|
|
229
|
+
|
|
230
|
+
assert len(records) == 4
|
|
231
|
+
|
|
232
|
+
assert records[0].url == "https://httpbin.org/get"
|
|
233
|
+
assert records[0].request.content == b""
|
|
234
|
+
assert records[1].url == "https://httpbin.org/get/abc"
|
|
235
|
+
assert records[1].request.content == b""
|
|
236
|
+
assert records[2].url == "https://httpbin.org/post"
|
|
237
|
+
assert records[2].request.content == b"abc"
|
|
238
|
+
assert records[3].url == "https://httpbin.org/get"
|
|
239
|
+
assert records[3].request.content == b""
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@pytest.mark.requests
|
|
243
|
+
def test_requests_many_requests_session():
|
|
244
|
+
with httpdbg() as records:
|
|
245
|
+
with requests.Session() as session:
|
|
246
|
+
session.get("https://httpbin.org/get")
|
|
247
|
+
session.get("https://httpbin.org/get/abc")
|
|
248
|
+
session.post("https://httpbin.org/post", data="abc")
|
|
249
|
+
session.get("https://httpbin.org/get")
|
|
250
|
+
|
|
251
|
+
assert len(records) == 4
|
|
252
|
+
|
|
253
|
+
assert records[0].url == "https://httpbin.org/get"
|
|
254
|
+
assert records[0].request.content == b""
|
|
255
|
+
assert records[1].url == "https://httpbin.org/get/abc"
|
|
256
|
+
assert records[1].request.content == b""
|
|
257
|
+
assert records[2].url == "https://httpbin.org/post"
|
|
258
|
+
assert records[2].request.content == b"abc"
|
|
259
|
+
assert records[3].url == "https://httpbin.org/get"
|
|
260
|
+
assert records[3].request.content == b""
|
|
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
|
|
File without changes
|
|
File without changes
|