@@ -14,7 +14,7 @@ def get_error_info():
14
14
return inspect .getframeinfo (caller_frame )
15
15
16
16
def is_external_url (url ):
17
- return isinstance (url , str ) and url .startswith (('http://' , 'https://' ))
17
+ return isinstance (url , str ) and url .startswith (('http://' , 'https://' )) and not url . startswith ( 'http://testserver' ) # FastAPI TestClient base url starts with http://testserver
18
18
19
19
# Store original methods
20
20
original_requests = {
@@ -32,7 +32,8 @@ def is_external_url(url):
32
32
'put' : httpx .put ,
33
33
'delete' : httpx .delete ,
34
34
'head' : httpx .head ,
35
- 'patch' : httpx .patch
35
+ 'patch' : httpx .patch ,
36
+ 'request' : httpx .request
36
37
}
37
38
38
39
original_httpx_client = {
@@ -63,7 +64,6 @@ def wrapper(*args, **kwargs):
63
64
def make_blocked_httpx_module (method_name , original_func ):
64
65
def wrapper (* args , ** kwargs ):
65
66
url = args [0 ] if args else kwargs .get ('url' , '' )
66
- print ("url:" , url )
67
67
if not is_external_url (url ):
68
68
filtered_kwargs = {k : v for k , v in kwargs .items () if v is not None }
69
69
return original_func (* args , ** filtered_kwargs )
@@ -77,34 +77,62 @@ def wrapper(*args, **kwargs):
77
77
78
78
def make_blocked_httpx_client (method_name , original_func ):
79
79
def wrapper (self , * args , ** kwargs ):
80
- url = args [0 ] if args else kwargs .get ('url' , '' )
81
- print ("url:" , url )
82
- if not is_external_url (url ):
80
+ from httpx import URL
81
+
82
+ if method_name == "request" and len (args ) >= 2 :
83
+ method , url_arg = args [0 ], args [1 ]
84
+ else :
85
+ url_arg = args [0 ] if args else kwargs .get ('url' , '' )
86
+
87
+ if isinstance (url_arg , str ) and hasattr (self , 'base_url' ) and self .base_url :
88
+ full_url = URL (self .base_url ).join (URL (url_arg ))
89
+ else :
90
+ full_url = url_arg
91
+
92
+ if not is_external_url (str (full_url )):
83
93
filtered_kwargs = {k : v for k , v in kwargs .items () if v is not None }
84
94
return original_func (self , * args , ** filtered_kwargs )
95
+
85
96
caller = get_error_info ()
86
97
raise RuntimeError (
87
- f"Blocked httpx.Client.{ method_name .upper ()} to { url } \n "
98
+ f"Blocked httpx.Client.{ method_name .upper ()} to { full_url } \n "
88
99
f"Called from: { caller .filename } :{ caller .lineno } in { caller .function } \n "
89
100
f"Please mock this request in your test."
90
101
)
102
+
91
103
return wrapper
104
+
92
105
93
106
def make_blocked_httpx_async_client (method_name , original_func ):
94
107
async def wrapper (self , * args , ** kwargs ):
95
- url = args [0 ] if args else kwargs .get ('url' , '' )
96
- print ("url:" , url )
97
- if not is_external_url (url ):
108
+ from httpx import URL
109
+
110
+ # Extract method and url argument based on call signature
111
+ if method_name == "request" and len (args ) >= 2 :
112
+ method , url_arg = args [0 ], args [1 ]
113
+ else :
114
+ url_arg = args [0 ] if args else kwargs .get ('url' , '' )
115
+
116
+ # Reconstruct full URL
117
+ if isinstance (url_arg , str ) and hasattr (self , 'base_url' ) and self .base_url :
118
+ full_url = URL (self .base_url ).join (URL (url_arg ))
119
+ else :
120
+ full_url = url_arg
121
+
122
+ if not is_external_url (str (full_url )):
98
123
filtered_kwargs = {k : v for k , v in kwargs .items () if v is not None }
99
124
return await original_func (self , * args , ** filtered_kwargs )
125
+
100
126
caller = get_error_info ()
101
127
raise RuntimeError (
102
- f"Blocked httpx.AsyncClient.{ method_name .upper ()} to { url } \n "
128
+ f"Blocked httpx.AsyncClient.{ method_name .upper ()} to { full_url } \n "
103
129
f"Called from: { caller .filename } :{ caller .lineno } in { caller .function } \n "
104
130
f"Please mock this request in your test."
105
131
)
132
+
106
133
return wrapper
107
134
135
+
108
136
def blocked_urllib (* args , ** kwargs ):
109
137
url = args [0 ] if args else kwargs .get ('url' , '' )
110
138
if not is_external_url (url ):
@@ -131,5 +159,6 @@ def blocked_urllib(*args, **kwargs):
131
159
# Patch httpx.AsyncClient instance methods
132
160
for method , original_func in original_httpx_async_client .items ():
133
161
monkeypatch .setattr (httpx .AsyncClient , method , make_blocked_httpx_async_client (method , original_func ))
162
+
134
163
# Patch urllib
135
- monkeypatch .setattr (urllib .request , "urlopen" , blocked_urllib )
164
+ monkeypatch .setattr (urllib .request , "urlopen" , blocked_urllib )
0 commit comments