@@ -36,75 +36,89 @@ def __init__(
36
36
self .disable_request_logging = config .get ("disable_request_logging" )
37
37
self .stream = stream
38
38
39
+ def __convert_params (self , params : Union [Dict [Any , Any ], List [Dict [Any , Any ]]]) -> Dict [str , str ]:
40
+ """
41
+ Convert parameters to string values for URL encoding.
42
+ """
43
+ if params is None :
44
+ return {}
45
+
46
+ if isinstance (params , str ):
47
+ return params
48
+
49
+ if isinstance (params , list ):
50
+ return {} # List params are only used in JSON body
51
+
52
+ converted = {}
53
+ for key , value in params .items ():
54
+ if isinstance (value , bool ):
55
+ converted [key ] = str (value ).lower ()
56
+ else :
57
+ converted [key ] = str (value )
58
+ return converted
59
+
39
60
async def perform (self ) -> Union [T , None ]:
40
61
"""
41
62
Async method to make an HTTP request to the JigsawStack API.
42
-
43
- Returns:
44
- Union[T, None]: A generic type of the Request class or None
45
-
46
- Raises:
47
- aiohttp.ClientResponseError: If the request fails
48
63
"""
49
64
async with self .__get_session () as session :
50
65
resp = await self .make_request (session , url = f"{ self .api_url } { self .path } " )
51
66
52
- # delete calls do not return a body
53
- if await resp .text () == "" and resp .status == 200 :
54
- return None
55
-
56
- # safety net for non-JSON responses
57
- content_type = resp .headers .get ("content-type" , "" )
58
- if "application/json" not in content_type :
59
- raise_for_code_and_type (
60
- code = 500 ,
61
- message = "Failed to parse JigsawStack API response. Please try again." ,
62
- )
67
+ # For binary responses
68
+ if resp .status == 200 :
69
+ content_type = resp .headers .get ("content-type" , "" )
70
+ if not resp .text or any (t in content_type for t in ["audio/" , "image/" , "application/octet-stream" , "image/png" ]):
71
+ content = await resp .read ()
72
+ return cast (T , content )
63
73
64
- # handle error responses
74
+ # For error responses
65
75
if resp .status != 200 :
66
- error = await resp .json ()
67
- raise_for_code_and_type (
68
- code = resp .status ,
69
- message = error .get ("message" ),
70
- err = error .get ("error" ),
71
- )
72
-
73
- return cast (T , await resp .json ())
74
-
75
- async def perform_file (self ) -> Union [aiohttp .ClientResponse , None ]:
76
- """
77
- Async method to make an HTTP request and return the raw response.
78
-
79
- Returns:
80
- Union[aiohttp.ClientResponse, None]: The raw response object
81
- """
76
+ try :
77
+ error = await resp .json ()
78
+ raise_for_code_and_type (
79
+ code = resp .status ,
80
+ message = error .get ("message" ),
81
+ err = error .get ("error" ),
82
+ )
83
+ except json .JSONDecodeError :
84
+ raise_for_code_and_type (
85
+ code = 500 ,
86
+ message = "Failed to parse response. Invalid content type or encoding." ,
87
+ )
88
+
89
+ # For JSON responses
90
+ try :
91
+ return cast (T , await resp .json ())
92
+ except json .JSONDecodeError :
93
+ content = await resp .read ()
94
+ return cast (T , content )
95
+
96
+ async def perform_file (self ) -> Union [T , None ]:
82
97
async with self .__get_session () as session :
83
98
resp = await self .make_request (session , url = f"{ self .api_url } { self .path } " )
84
99
85
- # delete calls do not return a body
86
- if await resp .text () == "" and resp .status == 200 :
87
- return None
88
-
89
- # handle error responses
90
- if (
91
- "application/json" not in resp .headers .get ("content-type" , "" )
92
- and resp .status != 200
93
- ):
94
- raise_for_code_and_type (
95
- code = 500 ,
96
- message = "Failed to parse JigsawStack API response. Please try again." ,
97
- error_type = "InternalServerError" ,
98
- )
99
-
100
100
if resp .status != 200 :
101
- error = await resp .json ()
102
- raise_for_code_and_type (
103
- code = resp .status ,
104
- message = error .get ("message" ),
105
- err = error .get ("error" ),
106
- )
107
- return resp
101
+ try :
102
+ error = await resp .json ()
103
+ raise_for_code_and_type (
104
+ code = resp .status ,
105
+ message = error .get ("message" ),
106
+ err = error .get ("error" ),
107
+ )
108
+ except json .JSONDecodeError :
109
+ raise_for_code_and_type (
110
+ code = 500 ,
111
+ message = "Failed to parse response. Invalid content type or encoding." ,
112
+ )
113
+
114
+ # For binary responses
115
+ if resp .status == 200 :
116
+ content_type = resp .headers .get ("content-type" , "" )
117
+ if "application/json" not in content_type :
118
+ content = await resp .read ()
119
+ return cast (T , content )
120
+
121
+ return cast (T , await resp .json ())
108
122
109
123
async def perform_with_content (self ) -> T :
110
124
"""
@@ -203,34 +217,36 @@ async def perform_with_content_streaming(
203
217
async def make_request (
204
218
self , session : aiohttp .ClientSession , url : str
205
219
) -> aiohttp .ClientResponse :
206
- """
207
- Make the actual async HTTP request.
208
-
209
- Args:
210
- session (aiohttp.ClientSession): The client session
211
- url (str): The URL to make the request to
212
-
213
- Returns:
214
- aiohttp.ClientResponse: The response object from the request
215
- """
216
220
headers = self .__get_headers ()
217
- params = self .params
218
221
verb = self .verb
219
222
data = self .data
220
223
221
- request_params = None if verb .lower () not in ["get" , "delete" ] else params
224
+ # Convert params to string values for URL encoding
225
+ converted_params = self .__convert_params (self .params )
222
226
223
- try :
227
+ if verb . lower () in [ "get" , "delete" ] :
224
228
return await session .request (
225
229
verb ,
226
230
url ,
227
- params = request_params ,
228
- json = params ,
231
+ params = converted_params ,
229
232
headers = headers ,
230
- data = data ,
231
233
)
232
- except aiohttp .ClientError as e :
233
- raise e
234
+ else :
235
+ if data is not None :
236
+ return await session .request (
237
+ verb ,
238
+ url ,
239
+ data = data ,
240
+ params = converted_params , # Use converted params
241
+ headers = headers ,
242
+ )
243
+ else :
244
+ return await session .request (
245
+ verb ,
246
+ url ,
247
+ json = self .params , # Keep JSON body as original
248
+ headers = headers ,
249
+ )
234
250
235
251
def __get_session (self ) -> aiohttp .ClientSession :
236
252
"""
0 commit comments