4
4
// ignore_for_file: invalid_annotation_target, unused_import
5
5
6
6
import 'dart:convert' ;
7
- import 'dart:io' as io;
8
7
import 'dart:typed_data' ;
9
8
10
9
import 'package:http/http.dart' as http;
@@ -21,7 +20,7 @@ enum HttpMethod { get, put, post, delete, options, head, patch, trace }
21
20
// ==========================================
22
21
23
22
/// HTTP exception handler for PineconeClient
24
- class PineconeClientException implements io. HttpException {
23
+ class PineconeClientException implements Exception {
25
24
PineconeClientException ({
26
25
required this .message,
27
26
required this .uri,
@@ -30,9 +29,7 @@ class PineconeClientException implements io.HttpException {
30
29
this .body,
31
30
});
32
31
33
- @override
34
32
final String message;
35
- @override
36
33
final Uri uri;
37
34
final HttpMethod method;
38
35
final int ? code;
@@ -69,11 +66,13 @@ class PineconeClient {
69
66
///
70
67
/// - [PineconeClient.baseUrl] Override base URL (default: server url defined in spec)
71
68
/// - [PineconeClient.headers] Global headers to be sent with every request
69
+ /// - [PineconeClient.queryParams] Global query parameters to be sent with every request
72
70
/// - [PineconeClient.client] Override HTTP client to use for requests
73
71
PineconeClient ({
74
72
this .apiKey = '' ,
75
73
this .baseUrl,
76
74
this .headers = const {},
75
+ this .queryParams = const {},
77
76
http.Client ? client,
78
77
}) : assert (
79
78
baseUrl == null || baseUrl.startsWith ('http' ),
@@ -91,6 +90,9 @@ class PineconeClient {
91
90
/// Global headers to be sent with every request
92
91
final Map <String , String > headers;
93
92
93
+ /// Global query parameters to be sent with every request
94
+ final Map <String , dynamic > queryParams;
95
+
94
96
/// HTTP client for requests
95
97
final http.Client client;
96
98
@@ -136,12 +138,20 @@ class PineconeClient {
136
138
}
137
139
138
140
// ------------------------------------------
139
- // METHOD: makeRequestStream
141
+ // METHOD: _jsonDecode
140
142
// ------------------------------------------
141
143
142
- /// Reusable request stream method
144
+ dynamic _jsonDecode (http.Response r) {
145
+ return json.decode (utf8.decode (r.bodyBytes));
146
+ }
147
+
148
+ // ------------------------------------------
149
+ // METHOD: _request
150
+ // ------------------------------------------
151
+
152
+ /// Reusable request method
143
153
@protected
144
- Future <http.StreamedResponse > makeRequestStream ({
154
+ Future <http.StreamedResponse > _request ({
145
155
required String baseUrl,
146
156
required String path,
147
157
required HttpMethod method,
@@ -161,6 +171,9 @@ class PineconeClient {
161
171
'baseUrl is required, but none defined in spec or provided by user' ,
162
172
);
163
173
174
+ // Add global query parameters
175
+ queryParams = {...queryParams, ...this .queryParams};
176
+
164
177
// Ensure query parameters are strings or iterable of strings
165
178
queryParams = queryParams.map ((key, value) {
166
179
if (value is Iterable ) {
@@ -193,46 +206,75 @@ class PineconeClient {
193
206
headers.addAll (this .headers);
194
207
195
208
// Build the request object
196
- late http.StreamedResponse response;
197
- try {
198
- http.BaseRequest request;
199
- if (isMultipart) {
200
- // Handle multipart request
201
- request = http.MultipartRequest (method.name, uri);
202
- request = request as http.MultipartRequest ;
203
- if (body is List <http.MultipartFile >) {
204
- request.files.addAll (body);
205
- } else {
206
- request.files.add (body as http.MultipartFile );
207
- }
209
+ http.BaseRequest request;
210
+ if (isMultipart) {
211
+ // Handle multipart request
212
+ request = http.MultipartRequest (method.name, uri);
213
+ request = request as http.MultipartRequest ;
214
+ if (body is List <http.MultipartFile >) {
215
+ request.files.addAll (body);
208
216
} else {
209
- // Handle normal request
210
- request = http.Request (method.name, uri);
211
- request = request as http.Request ;
212
- try {
213
- if (body != null ) {
214
- request.body = json.encode (body);
215
- }
216
- } catch (e) {
217
- // Handle request encoding error
218
- throw PineconeClientException (
219
- uri: uri,
220
- method: method,
221
- message: 'Could not encode: ${body .runtimeType }' ,
222
- body: e,
223
- );
217
+ request.files.add (body as http.MultipartFile );
218
+ }
219
+ } else {
220
+ // Handle normal request
221
+ request = http.Request (method.name, uri);
222
+ request = request as http.Request ;
223
+ try {
224
+ if (body != null ) {
225
+ request.body = json.encode (body);
224
226
}
227
+ } catch (e) {
228
+ // Handle request encoding error
229
+ throw PineconeClientException (
230
+ uri: uri,
231
+ method: method,
232
+ message: 'Could not encode: ${body .runtimeType }' ,
233
+ body: e,
234
+ );
225
235
}
236
+ }
226
237
227
- // Add request headers
228
- request.headers.addAll (headers);
238
+ // Add request headers
239
+ request.headers.addAll (headers);
229
240
230
- // Handle user request middleware
231
- request = await onRequest (request);
241
+ // Handle user request middleware
242
+ request = await onRequest (request);
243
+
244
+ // Submit request
245
+ return await client.send (request);
246
+ }
232
247
233
- // Submit request
234
- response = await client.send (request);
248
+ // ------------------------------------------
249
+ // METHOD: makeRequestStream
250
+ // ------------------------------------------
235
251
252
+ /// Reusable request stream method
253
+ @protected
254
+ Future <http.StreamedResponse > makeRequestStream ({
255
+ required String baseUrl,
256
+ required String path,
257
+ required HttpMethod method,
258
+ Map <String , dynamic > queryParams = const {},
259
+ Map <String , String > headerParams = const {},
260
+ bool isMultipart = false ,
261
+ String requestType = '' ,
262
+ String responseType = '' ,
263
+ Object ? body,
264
+ }) async {
265
+ final uri = Uri .parse ((this .baseUrl ?? baseUrl) + path);
266
+ late http.StreamedResponse response;
267
+ try {
268
+ response = await _request (
269
+ baseUrl: baseUrl,
270
+ path: path,
271
+ method: method,
272
+ queryParams: queryParams,
273
+ headerParams: headerParams,
274
+ requestType: requestType,
275
+ responseType: responseType,
276
+ body: body,
277
+ );
236
278
// Handle user response middleware
237
279
response = await onStreamedResponse (response);
238
280
} catch (e) {
@@ -277,8 +319,10 @@ class PineconeClient {
277
319
String responseType = '' ,
278
320
Object ? body,
279
321
}) async {
322
+ final uri = Uri .parse ((this .baseUrl ?? baseUrl) + path);
323
+ late http.Response response;
280
324
try {
281
- final streamedResponse = await makeRequestStream (
325
+ final streamedResponse = await _request (
282
326
baseUrl: baseUrl,
283
327
path: path,
284
328
method: method,
@@ -288,21 +332,32 @@ class PineconeClient {
288
332
responseType: responseType,
289
333
body: body,
290
334
);
291
- final response = await http.Response .fromStream (streamedResponse);
292
-
335
+ response = await http.Response .fromStream (streamedResponse);
293
336
// Handle user response middleware
294
- return await onResponse (response);
295
- } on PineconeClientException {
296
- rethrow ;
337
+ response = await onResponse (response);
297
338
} catch (e) {
298
339
// Handle request and response errors
299
340
throw PineconeClientException (
300
- uri: Uri . parse (( this .baseUrl ?? baseUrl) + path) ,
341
+ uri: uri ,
301
342
method: method,
302
343
message: 'Response error' ,
303
344
body: e,
304
345
);
305
346
}
347
+
348
+ // Check for successful response
349
+ if ((response.statusCode ~ / 100 ) == 2 ) {
350
+ return response;
351
+ }
352
+
353
+ // Handle unsuccessful response
354
+ throw PineconeClientException (
355
+ uri: uri,
356
+ method: method,
357
+ message: 'Unsuccessful response' ,
358
+ code: response.statusCode,
359
+ body: response.body,
360
+ );
306
361
}
307
362
308
363
// ------------------------------------------
@@ -330,7 +385,7 @@ class PineconeClient {
330
385
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
331
386
},
332
387
);
333
- return List <String >.from (json. decode (r.body ));
388
+ return List <String >.from (_jsonDecode (r ));
334
389
}
335
390
336
391
// ------------------------------------------
@@ -392,7 +447,7 @@ class PineconeClient {
392
447
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
393
448
},
394
449
);
395
- return Collection .fromJson (json. decode (r.body ));
450
+ return Collection .fromJson (_jsonDecode (r ));
396
451
}
397
452
398
453
// ------------------------------------------
@@ -450,7 +505,7 @@ class PineconeClient {
450
505
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
451
506
},
452
507
);
453
- return List <String >.from (json. decode (r.body ));
508
+ return List <String >.from (_jsonDecode (r ));
454
509
}
455
510
456
511
// ------------------------------------------
@@ -512,7 +567,7 @@ class PineconeClient {
512
567
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
513
568
},
514
569
);
515
- return Index .fromJson (json. decode (r.body ));
570
+ return Index .fromJson (_jsonDecode (r ));
516
571
}
517
572
518
573
// ------------------------------------------
@@ -615,7 +670,7 @@ class PineconeClient {
615
670
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
616
671
},
617
672
);
618
- return IndexStats .fromJson (json. decode (r.body ));
673
+ return IndexStats .fromJson (_jsonDecode (r ));
619
674
}
620
675
621
676
// ------------------------------------------
@@ -654,7 +709,7 @@ class PineconeClient {
654
709
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
655
710
},
656
711
);
657
- return QueryResponse .fromJson (json. decode (r.body ));
712
+ return QueryResponse .fromJson (_jsonDecode (r ));
658
713
}
659
714
660
715
// ------------------------------------------
@@ -737,7 +792,7 @@ class PineconeClient {
737
792
if (namespace != null ) 'namespace' : namespace,
738
793
},
739
794
);
740
- return FetchResponse .fromJson (json. decode (r.body ));
795
+ return FetchResponse .fromJson (_jsonDecode (r ));
741
796
}
742
797
743
798
// ------------------------------------------
@@ -814,6 +869,6 @@ class PineconeClient {
814
869
if (apiKey.isNotEmpty) 'Api-Key' : apiKey,
815
870
},
816
871
);
817
- return UpsertResponse .fromJson (json. decode (r.body ));
872
+ return UpsertResponse .fromJson (_jsonDecode (r ));
818
873
}
819
874
}
0 commit comments