Skip to content

Commit e241101

Browse files
authored
feat(dart): make requests abortable (#23930)
* templates * samples * empty body guard
1 parent 0393d39 commit e241101

14 files changed

Lines changed: 323 additions & 252 deletions

File tree

modules/openapi-generator/src/main/resources/dart2/api.mustache

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class {{{classname}}} {
5050
///
5151
{{/-last}}
5252
{{/allParams}}
53-
Future<Response> {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
53+
Future<Response> {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}, {{/required}}{{/allParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}}, {{/required}}{{/allParams}}Future<void>? abortTrigger, }) async {
5454
// ignore: prefer_const_declarations
5555
final path = r'{{{path}}}'{{#pathParams}}
5656
.replaceAll({{=<% %>=}}'{<% baseName %>}'<%={{ }}=%>, {{{paramName}}}{{^isString}}.toString(){{/isString}}){{/pathParams}};
@@ -129,6 +129,7 @@ class {{{classname}}} {
129129
headerParams,
130130
formParams,
131131
contentTypes.isEmpty ? null : contentTypes.first,
132+
abortTrigger: abortTrigger,
132133
);
133134
}
134135

@@ -162,8 +163,8 @@ class {{{classname}}} {
162163
///
163164
{{/-last}}
164165
{{/allParams}}
165-
Future<{{#returnType}}{{{.}}}?{{/returnType}}{{^returnType}}void{{/returnType}}> {{{nickname}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
166-
final response = await {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}} {{#allParams}}{{^required}}{{{paramName}}}: {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} {{/hasOptionalParams}});
166+
Future<{{#returnType}}{{{.}}}?{{/returnType}}{{^returnType}}void{{/returnType}}> {{{nickname}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}, {{/required}}{{/allParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}}, {{/required}}{{/allParams}}Future<void>? abortTrigger, }) async {
167+
final response = await {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{paramName}}}, {{/required}}{{/allParams}}{{#allParams}}{{^required}}{{{paramName}}}: {{{paramName}}}, {{/required}}{{/allParams}}abortTrigger: abortTrigger,);
167168
if (response.statusCode >= HttpStatus.badRequest) {
168169
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
169170
}

modules/openapi-generator/src/main/resources/dart2/api_client.mustache

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ class ApiClient {
3535
Object? body,
3636
Map<String, String> headerParams,
3737
Map<String, String> formParams,
38-
String? contentType,
39-
) async {
38+
String? contentType, {
39+
Future<void>? abortTrigger,
40+
}) async {
4041
await authentication?.applyToParams(queryParams, headerParams);
4142
4243
headerParams.addAll(_defaultHeaderMap);
@@ -54,7 +55,7 @@ class ApiClient {
5455
body is MultipartFile && (contentType == null ||
5556
!contentType.toLowerCase().startsWith('multipart/form-data'))
5657
) {
57-
final request = StreamedRequest(method, uri);
58+
final request = AbortableStreamedRequest(method, uri, abortTrigger: abortTrigger);
5859
request.headers.addAll(headerParams);
5960
request.contentLength = body.length;
6061
body.finalize().listen(
@@ -69,7 +70,7 @@ class ApiClient {
6970
}
7071
7172
if (body is MultipartRequest) {
72-
final request = MultipartRequest(method, uri);
73+
final request = AbortableMultipartRequest(method, uri, abortTrigger: abortTrigger);
7374
request.fields.addAll(body.fields);
7475
request.files.addAll(body.files);
7576
request.headers.addAll(body.headers);
@@ -83,14 +84,19 @@ class ApiClient {
8384
: await serializeAsync(body);
8485
final nullableHeaderParams = headerParams.isEmpty ? null : headerParams;
8586
86-
switch(method) {
87-
case 'POST': return await _client.post(uri, headers: nullableHeaderParams, body: msgBody,);
88-
case 'PUT': return await _client.put(uri, headers: nullableHeaderParams, body: msgBody,);
89-
case 'DELETE': return await _client.delete(uri, headers: nullableHeaderParams, body: msgBody,);
90-
case 'PATCH': return await _client.patch(uri, headers: nullableHeaderParams, body: msgBody,);
91-
case 'HEAD': return await _client.head(uri, headers: nullableHeaderParams,);
92-
case 'GET': return await _client.get(uri, headers: nullableHeaderParams,);
87+
final request = AbortableRequest(method, uri, abortTrigger: abortTrigger);
88+
if (nullableHeaderParams != null) {
89+
request.headers.addAll(nullableHeaderParams);
9390
}
91+
if (msgBody is String && msgBody.isNotEmpty) {
92+
request.body = msgBody;
93+
} else if (msgBody is List<int> && msgBody.isNotEmpty) {
94+
request.bodyBytes = msgBody;
95+
} else if (msgBody is Map<String, String>) {
96+
request.bodyFields = msgBody;
97+
}
98+
final response = await _client.send(request);
99+
return Response.fromStream(response);
94100
} on SocketException catch (error, trace) {
95101
throw ApiException.withInner(
96102
HttpStatus.badRequest,
@@ -127,11 +133,6 @@ class ApiClient {
127133
trace,
128134
);
129135
}
130-
131-
throw ApiException(
132-
HttpStatus.badRequest,
133-
'Invalid HTTP operation: $method $path',
134-
);
135136
}
136137
{{#native_serialization}}
137138

samples/openapi3/client/petstore/dart2/petstore_client_lib/lib/api/pet_api.dart

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class PetApi {
2626
///
2727
/// * [Pet] pet (required):
2828
/// Pet object that needs to be added to the store
29-
Future<Response> addPetWithHttpInfo(Pet pet,) async {
29+
Future<Response> addPetWithHttpInfo(Pet pet, { Future<void>? abortTrigger, }) async {
3030
// ignore: prefer_const_declarations
3131
final path = r'/pet';
3232

@@ -48,6 +48,7 @@ class PetApi {
4848
headerParams,
4949
formParams,
5050
contentTypes.isEmpty ? null : contentTypes.first,
51+
abortTrigger: abortTrigger,
5152
);
5253
}
5354

@@ -59,8 +60,8 @@ class PetApi {
5960
///
6061
/// * [Pet] pet (required):
6162
/// Pet object that needs to be added to the store
62-
Future<Pet?> addPet(Pet pet,) async {
63-
final response = await addPetWithHttpInfo(pet,);
63+
Future<Pet?> addPet(Pet pet, { Future<void>? abortTrigger, }) async {
64+
final response = await addPetWithHttpInfo(pet, abortTrigger: abortTrigger,);
6465
if (response.statusCode >= HttpStatus.badRequest) {
6566
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
6667
}
@@ -86,7 +87,7 @@ class PetApi {
8687
/// Pet id to delete
8788
///
8889
/// * [String] apiKey:
89-
Future<Response> deletePetWithHttpInfo(int petId, { String? apiKey, }) async {
90+
Future<Response> deletePetWithHttpInfo(int petId, { String? apiKey, Future<void>? abortTrigger, }) async {
9091
// ignore: prefer_const_declarations
9192
final path = r'/pet/{petId}'
9293
.replaceAll('{petId}', petId.toString());
@@ -113,6 +114,7 @@ class PetApi {
113114
headerParams,
114115
formParams,
115116
contentTypes.isEmpty ? null : contentTypes.first,
117+
abortTrigger: abortTrigger,
116118
);
117119
}
118120

@@ -126,8 +128,8 @@ class PetApi {
126128
/// Pet id to delete
127129
///
128130
/// * [String] apiKey:
129-
Future<void> deletePet(int petId, { String? apiKey, }) async {
130-
final response = await deletePetWithHttpInfo(petId, apiKey: apiKey, );
131+
Future<void> deletePet(int petId, { String? apiKey, Future<void>? abortTrigger, }) async {
132+
final response = await deletePetWithHttpInfo(petId, apiKey: apiKey, abortTrigger: abortTrigger,);
131133
if (response.statusCode >= HttpStatus.badRequest) {
132134
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
133135
}
@@ -143,7 +145,7 @@ class PetApi {
143145
///
144146
/// * [List<String>] status (required):
145147
/// Status values that need to be considered for filter
146-
Future<Response> findPetsByStatusWithHttpInfo(List<String> status,) async {
148+
Future<Response> findPetsByStatusWithHttpInfo(List<String> status, { Future<void>? abortTrigger, }) async {
147149
// ignore: prefer_const_declarations
148150
final path = r'/pet/findByStatus';
149151

@@ -167,6 +169,7 @@ class PetApi {
167169
headerParams,
168170
formParams,
169171
contentTypes.isEmpty ? null : contentTypes.first,
172+
abortTrigger: abortTrigger,
170173
);
171174
}
172175

@@ -178,8 +181,8 @@ class PetApi {
178181
///
179182
/// * [List<String>] status (required):
180183
/// Status values that need to be considered for filter
181-
Future<List<Pet>?> findPetsByStatus(List<String> status,) async {
182-
final response = await findPetsByStatusWithHttpInfo(status,);
184+
Future<List<Pet>?> findPetsByStatus(List<String> status, { Future<void>? abortTrigger, }) async {
185+
final response = await findPetsByStatusWithHttpInfo(status, abortTrigger: abortTrigger,);
183186
if (response.statusCode >= HttpStatus.badRequest) {
184187
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
185188
}
@@ -206,7 +209,7 @@ class PetApi {
206209
///
207210
/// * [List<String>] tags (required):
208211
/// Tags to filter by
209-
Future<Response> findPetsByTagsWithHttpInfo(List<String> tags,) async {
212+
Future<Response> findPetsByTagsWithHttpInfo(List<String> tags, { Future<void>? abortTrigger, }) async {
210213
// ignore: prefer_const_declarations
211214
final path = r'/pet/findByTags';
212215

@@ -230,6 +233,7 @@ class PetApi {
230233
headerParams,
231234
formParams,
232235
contentTypes.isEmpty ? null : contentTypes.first,
236+
abortTrigger: abortTrigger,
233237
);
234238
}
235239

@@ -241,8 +245,8 @@ class PetApi {
241245
///
242246
/// * [List<String>] tags (required):
243247
/// Tags to filter by
244-
Future<List<Pet>?> findPetsByTags(List<String> tags,) async {
245-
final response = await findPetsByTagsWithHttpInfo(tags,);
248+
Future<List<Pet>?> findPetsByTags(List<String> tags, { Future<void>? abortTrigger, }) async {
249+
final response = await findPetsByTagsWithHttpInfo(tags, abortTrigger: abortTrigger,);
246250
if (response.statusCode >= HttpStatus.badRequest) {
247251
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
248252
}
@@ -269,7 +273,7 @@ class PetApi {
269273
///
270274
/// * [int] petId (required):
271275
/// ID of pet to return
272-
Future<Response> getPetByIdWithHttpInfo(int petId,) async {
276+
Future<Response> getPetByIdWithHttpInfo(int petId, { Future<void>? abortTrigger, }) async {
273277
// ignore: prefer_const_declarations
274278
final path = r'/pet/{petId}'
275279
.replaceAll('{petId}', petId.toString());
@@ -292,6 +296,7 @@ class PetApi {
292296
headerParams,
293297
formParams,
294298
contentTypes.isEmpty ? null : contentTypes.first,
299+
abortTrigger: abortTrigger,
295300
);
296301
}
297302

@@ -303,8 +308,8 @@ class PetApi {
303308
///
304309
/// * [int] petId (required):
305310
/// ID of pet to return
306-
Future<Pet?> getPetById(int petId,) async {
307-
final response = await getPetByIdWithHttpInfo(petId,);
311+
Future<Pet?> getPetById(int petId, { Future<void>? abortTrigger, }) async {
312+
final response = await getPetByIdWithHttpInfo(petId, abortTrigger: abortTrigger,);
308313
if (response.statusCode >= HttpStatus.badRequest) {
309314
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
310315
}
@@ -328,7 +333,7 @@ class PetApi {
328333
///
329334
/// * [Pet] pet (required):
330335
/// Pet object that needs to be added to the store
331-
Future<Response> updatePetWithHttpInfo(Pet pet,) async {
336+
Future<Response> updatePetWithHttpInfo(Pet pet, { Future<void>? abortTrigger, }) async {
332337
// ignore: prefer_const_declarations
333338
final path = r'/pet';
334339

@@ -350,6 +355,7 @@ class PetApi {
350355
headerParams,
351356
formParams,
352357
contentTypes.isEmpty ? null : contentTypes.first,
358+
abortTrigger: abortTrigger,
353359
);
354360
}
355361

@@ -361,8 +367,8 @@ class PetApi {
361367
///
362368
/// * [Pet] pet (required):
363369
/// Pet object that needs to be added to the store
364-
Future<Pet?> updatePet(Pet pet,) async {
365-
final response = await updatePetWithHttpInfo(pet,);
370+
Future<Pet?> updatePet(Pet pet, { Future<void>? abortTrigger, }) async {
371+
final response = await updatePetWithHttpInfo(pet, abortTrigger: abortTrigger,);
366372
if (response.statusCode >= HttpStatus.badRequest) {
367373
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
368374
}
@@ -392,7 +398,7 @@ class PetApi {
392398
///
393399
/// * [String] status:
394400
/// Updated status of the pet
395-
Future<Response> updatePetWithFormWithHttpInfo(int petId, { String? name, String? status, }) async {
401+
Future<Response> updatePetWithFormWithHttpInfo(int petId, { String? name, String? status, Future<void>? abortTrigger, }) async {
396402
// ignore: prefer_const_declarations
397403
final path = r'/pet/{petId}'
398404
.replaceAll('{petId}', petId.toString());
@@ -421,6 +427,7 @@ class PetApi {
421427
headerParams,
422428
formParams,
423429
contentTypes.isEmpty ? null : contentTypes.first,
430+
abortTrigger: abortTrigger,
424431
);
425432
}
426433

@@ -438,8 +445,8 @@ class PetApi {
438445
///
439446
/// * [String] status:
440447
/// Updated status of the pet
441-
Future<void> updatePetWithForm(int petId, { String? name, String? status, }) async {
442-
final response = await updatePetWithFormWithHttpInfo(petId, name: name, status: status, );
448+
Future<void> updatePetWithForm(int petId, { String? name, String? status, Future<void>? abortTrigger, }) async {
449+
final response = await updatePetWithFormWithHttpInfo(petId, name: name, status: status, abortTrigger: abortTrigger,);
443450
if (response.statusCode >= HttpStatus.badRequest) {
444451
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
445452
}
@@ -461,7 +468,7 @@ class PetApi {
461468
///
462469
/// * [MultipartFile] file:
463470
/// file to upload
464-
Future<Response> uploadFileWithHttpInfo(int petId, { String? additionalMetadata, MultipartFile? file, }) async {
471+
Future<Response> uploadFileWithHttpInfo(int petId, { String? additionalMetadata, MultipartFile? file, Future<void>? abortTrigger, }) async {
465472
// ignore: prefer_const_declarations
466473
final path = r'/pet/{petId}/uploadImage'
467474
.replaceAll('{petId}', petId.toString());
@@ -498,6 +505,7 @@ class PetApi {
498505
headerParams,
499506
formParams,
500507
contentTypes.isEmpty ? null : contentTypes.first,
508+
abortTrigger: abortTrigger,
501509
);
502510
}
503511

@@ -515,8 +523,8 @@ class PetApi {
515523
///
516524
/// * [MultipartFile] file:
517525
/// file to upload
518-
Future<ApiResponse?> uploadFile(int petId, { String? additionalMetadata, MultipartFile? file, }) async {
519-
final response = await uploadFileWithHttpInfo(petId, additionalMetadata: additionalMetadata, file: file, );
526+
Future<ApiResponse?> uploadFile(int petId, { String? additionalMetadata, MultipartFile? file, Future<void>? abortTrigger, }) async {
527+
final response = await uploadFileWithHttpInfo(petId, additionalMetadata: additionalMetadata, file: file, abortTrigger: abortTrigger,);
520528
if (response.statusCode >= HttpStatus.badRequest) {
521529
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
522530
}

0 commit comments

Comments
 (0)