From 3c869d5b12595dba739a6c9168f63f9e6c655969 Mon Sep 17 00:00:00 2001 From: Noor Dawod Date: Tue, 13 Oct 2020 17:30:49 +0200 Subject: [PATCH] [Fix/Dart2] Resolve an exception with status 204 and no body. (#7647) * Resolve an exception situation when a remote server returns 204 with no body. * Only return a value when needed. * Use HttpStatus codes instead of magic numbers. * Drop checking for a body as it will consume too much memory. * Cosmetic changes. --- .../src/main/resources/dart2/api.mustache | 24 +++--- .../main/resources/dart2/api_client.mustache | 14 ++-- .../main/resources/dart2/api_helper.mustache | 4 +- .../petstore_client_lib/lib/api/pet_api.dart | 76 ++++++++++--------- .../lib/api/store_api.dart | 40 +++++----- .../petstore_client_lib/lib/api/user_api.dart | 73 ++++++++---------- .../petstore_client_lib/lib/api_client.dart | 14 ++-- .../petstore_client_lib/lib/api_helper.dart | 4 +- 8 files changed, 125 insertions(+), 124 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/dart2/api.mustache b/modules/openapi-generator/src/main/resources/dart2/api.mustache index e032490bb4e..a7811afeb51 100644 --- a/modules/openapi-generator/src/main/resources/dart2/api.mustache +++ b/modules/openapi-generator/src/main/resources/dart2/api.mustache @@ -50,16 +50,19 @@ class {{{classname}}} { {{/hasMore}} {{/allParams}} {{#returnType}}Future {{/returnType}}{{^returnType}}Future {{/returnType}}{{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}} {{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async { + {{#hasParams}} // Verify required params are set. {{#allParams}} {{#required}} if ({{{paramName}}} == null) { - throw ApiException(400, 'Missing required param: {{{paramName}}}'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: {{{paramName}}}'); } {{/required}} {{/allParams}} - final path = '{{{path}}}'.replaceAll('{format}', 'json'){{#pathParams}}.replaceAll('{' + '{{{baseName}}}' + '}', {{{paramName}}}.toString()){{/pathParams}}; + {{/hasParams}} + final path = '{{{path}}}'.replaceAll('{format}', 'json'){{#pathParams}} + .replaceAll('{' + '{{{baseName}}}' + '}', {{{paramName}}}.toString()){{/pathParams}}; Object postBody{{#bodyParam}} = {{{paramName}}}{{/bodyParam}}; @@ -162,31 +165,30 @@ class {{{classname}}} { {{/allParams}} {{#returnType}}Future<{{{returnType}}}> {{/returnType}}{{^returnType}}Future {{/returnType}}{{{nickname}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}} {{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async { final response = await {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}}{{#hasOptionalParams}} {{#allParams}}{{^required}}{{{paramName}}}: {{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}} {{/hasOptionalParams}}); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + {{#returnType}} + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { {{#isListContainer}} - {{#returnType}} return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List) .map((item) => item as {{{returnBaseType}}}) .toList(growable: false); - {{/returnType}} {{/isListContainer}} {{^isListContainer}} {{#isMap}} - {{#returnType}} return {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}')); - {{/returnType}} {{/isMap}} {{^isMap}} - {{#returnType}} return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}}; - {{/returnType}} {{/isMap}} {{/isListContainer}} } - return{{#returnType}} null{{/returnType}}; + return null; + {{/returnType}} } {{/operation}} } diff --git a/modules/openapi-generator/src/main/resources/dart2/api_client.mustache b/modules/openapi-generator/src/main/resources/dart2/api_client.mustache index 340978123e7..6fab896fa79 100644 --- a/modules/openapi-generator/src/main/resources/dart2/api_client.mustache +++ b/modules/openapi-generator/src/main/resources/dart2/api_client.mustache @@ -125,16 +125,16 @@ class ApiClient { case 'GET': return await _client.get(url, headers: nullableHeaderParams); } } on SocketException catch (e, trace) { - throw ApiException.withInner(400, 'Socket operation failed: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'Socket operation failed: $method $path', e, trace); } on TlsException catch (e, trace) { - throw ApiException.withInner(400, 'TLS/SSL communication failed: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'TLS/SSL communication failed: $method $path', e, trace); } on IOException catch (e, trace) { - throw ApiException.withInner(400, 'I/O operation failed: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'I/O operation failed: $method $path', e, trace); } on Exception catch (e, trace) { - throw ApiException.withInner(400, 'Exception occurred: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'Exception occurred: $method $path', e, trace); } - throw ApiException(400, 'Invalid HTTP operation: $method $path'); + throw ApiException(HttpStatus.badRequest, 'Invalid HTTP operation: $method $path'); } dynamic _deserialize(dynamic value, String targetType, {bool growable}) { @@ -182,9 +182,9 @@ class ApiClient { break; } } on Exception catch (e, stack) { - throw ApiException.withInner(500, 'Exception during deserialization.', e, stack); + throw ApiException.withInner(HttpStatus.internalServerError, 'Exception during deserialization.', e, stack); } - throw ApiException(500, 'Could not find a suitable class for deserialization'); + throw ApiException(HttpStatus.internalServerError, 'Could not find a suitable class for deserialization'); } /// Update query and header parameters based on authentication settings. diff --git a/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache b/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache index 35300254aa1..e851e731433 100644 --- a/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache +++ b/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache @@ -55,7 +55,7 @@ String parameterToString(dynamic value) { /// content type. Otherwise, returns the decoded body as decoded by dart:http package. String _decodeBodyBytes(Response response) { final contentType = response.headers['content-type']; - return contentType != null && contentType.contains('application/json') - ? utf8.decode(response.bodyBytes) + return contentType != null && contentType.toLowerCase().startsWith('application/json') + ? response.bodyBytes == null ? null : utf8.decode(response.bodyBytes) : response.body; } diff --git a/samples/client/petstore/dart2/petstore_client_lib/lib/api/pet_api.dart b/samples/client/petstore/dart2/petstore_client_lib/lib/api/pet_api.dart index 772154d7801..c5ae7ae2bed 100644 --- a/samples/client/petstore/dart2/petstore_client_lib/lib/api/pet_api.dart +++ b/samples/client/petstore/dart2/petstore_client_lib/lib/api/pet_api.dart @@ -26,7 +26,7 @@ class PetApi { Future addPetWithHttpInfo(Pet body) async { // Verify required params are set. if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } final path = '/pet'.replaceAll('{format}', 'json'); @@ -74,12 +74,9 @@ class PetApi { /// Pet object that needs to be added to the store Future addPet(Pet body) async { final response = await addPetWithHttpInfo(body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Deletes a pet @@ -95,10 +92,11 @@ class PetApi { Future deletePetWithHttpInfo(int petId, { String apiKey }) async { // Verify required params are set. if (petId == null) { - throw ApiException(400, 'Missing required param: petId'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: petId'); } - final path = '/pet/{petId}'.replaceAll('{format}', 'json').replaceAll('{' + 'petId' + '}', petId.toString()); + final path = '/pet/{petId}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'petId' + '}', petId.toString()); Object postBody; @@ -146,12 +144,9 @@ class PetApi { /// * [String] apiKey: Future deletePet(int petId, { String apiKey }) async { final response = await deletePetWithHttpInfo(petId, apiKey: apiKey ); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Finds Pets by status @@ -167,7 +162,7 @@ class PetApi { Future findPetsByStatusWithHttpInfo(List status) async { // Verify required params are set. if (status == null) { - throw ApiException(400, 'Missing required param: status'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: status'); } final path = '/pet/findByStatus'.replaceAll('{format}', 'json'); @@ -218,10 +213,13 @@ class PetApi { /// Status values that need to be considered for filter Future> findPetsByStatus(List status) async { final response = await findPetsByStatusWithHttpInfo(status); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return (apiClient.deserialize(_decodeBodyBytes(response), 'List') as List) .map((item) => item as Pet) .toList(growable: false); @@ -242,7 +240,7 @@ class PetApi { Future findPetsByTagsWithHttpInfo(List tags) async { // Verify required params are set. if (tags == null) { - throw ApiException(400, 'Missing required param: tags'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: tags'); } final path = '/pet/findByTags'.replaceAll('{format}', 'json'); @@ -293,10 +291,13 @@ class PetApi { /// Tags to filter by Future> findPetsByTags(List tags) async { final response = await findPetsByTagsWithHttpInfo(tags); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return (apiClient.deserialize(_decodeBodyBytes(response), 'List') as List) .map((item) => item as Pet) .toList(growable: false); @@ -317,10 +318,11 @@ class PetApi { Future getPetByIdWithHttpInfo(int petId) async { // Verify required params are set. if (petId == null) { - throw ApiException(400, 'Missing required param: petId'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: petId'); } - final path = '/pet/{petId}'.replaceAll('{format}', 'json').replaceAll('{' + 'petId' + '}', petId.toString()); + final path = '/pet/{petId}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'petId' + '}', petId.toString()); Object postBody; @@ -367,10 +369,13 @@ class PetApi { /// ID of pet to return Future getPetById(int petId) async { final response = await getPetByIdWithHttpInfo(petId); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return apiClient.deserialize(_decodeBodyBytes(response), 'Pet') as Pet; } return null; @@ -387,7 +392,7 @@ class PetApi { Future updatePetWithHttpInfo(Pet body) async { // Verify required params are set. if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } final path = '/pet'.replaceAll('{format}', 'json'); @@ -435,12 +440,9 @@ class PetApi { /// Pet object that needs to be added to the store Future updatePet(Pet body) async { final response = await updatePetWithHttpInfo(body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Updates a pet in the store with form data @@ -460,10 +462,11 @@ class PetApi { Future updatePetWithFormWithHttpInfo(int petId, { String name, String status }) async { // Verify required params are set. if (petId == null) { - throw ApiException(400, 'Missing required param: petId'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: petId'); } - final path = '/pet/{petId}'.replaceAll('{format}', 'json').replaceAll('{' + 'petId' + '}', petId.toString()); + final path = '/pet/{petId}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'petId' + '}', petId.toString()); Object postBody; @@ -528,12 +531,9 @@ class PetApi { /// Updated status of the pet Future updatePetWithForm(int petId, { String name, String status }) async { final response = await updatePetWithFormWithHttpInfo(petId, name: name, status: status ); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// uploads an image @@ -553,10 +553,11 @@ class PetApi { Future uploadFileWithHttpInfo(int petId, { String additionalMetadata, MultipartFile file }) async { // Verify required params are set. if (petId == null) { - throw ApiException(400, 'Missing required param: petId'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: petId'); } - final path = '/pet/{petId}/uploadImage'.replaceAll('{format}', 'json').replaceAll('{' + 'petId' + '}', petId.toString()); + final path = '/pet/{petId}/uploadImage'.replaceAll('{format}', 'json') + .replaceAll('{' + 'petId' + '}', petId.toString()); Object postBody; @@ -619,10 +620,13 @@ class PetApi { /// file to upload Future uploadFile(int petId, { String additionalMetadata, MultipartFile file }) async { final response = await uploadFileWithHttpInfo(petId, additionalMetadata: additionalMetadata, file: file ); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return apiClient.deserialize(_decodeBodyBytes(response), 'ApiResponse') as ApiResponse; } return null; diff --git a/samples/client/petstore/dart2/petstore_client_lib/lib/api/store_api.dart b/samples/client/petstore/dart2/petstore_client_lib/lib/api/store_api.dart index dbb8b77da2a..dca969b77ed 100644 --- a/samples/client/petstore/dart2/petstore_client_lib/lib/api/store_api.dart +++ b/samples/client/petstore/dart2/petstore_client_lib/lib/api/store_api.dart @@ -28,10 +28,11 @@ class StoreApi { Future deleteOrderWithHttpInfo(String orderId) async { // Verify required params are set. if (orderId == null) { - throw ApiException(400, 'Missing required param: orderId'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: orderId'); } - final path = '/store/order/{orderId}'.replaceAll('{format}', 'json').replaceAll('{' + 'orderId' + '}', orderId.toString()); + final path = '/store/order/{orderId}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'orderId' + '}', orderId.toString()); Object postBody; @@ -78,12 +79,9 @@ class StoreApi { /// ID of the order that needs to be deleted Future deleteOrder(String orderId) async { final response = await deleteOrderWithHttpInfo(orderId); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Returns pet inventories by status @@ -92,8 +90,6 @@ class StoreApi { /// /// Note: This method returns the HTTP [Response]. Future getInventoryWithHttpInfo() async { - // Verify required params are set. - final path = '/store/inventory'.replaceAll('{format}', 'json'); Object postBody; @@ -136,10 +132,13 @@ class StoreApi { /// Returns a map of status codes to quantities Future> getInventory() async { final response = await getInventoryWithHttpInfo(); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return Map.from(apiClient.deserialize(_decodeBodyBytes(response), 'Map')); } return null; @@ -158,10 +157,11 @@ class StoreApi { Future getOrderByIdWithHttpInfo(int orderId) async { // Verify required params are set. if (orderId == null) { - throw ApiException(400, 'Missing required param: orderId'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: orderId'); } - final path = '/store/order/{orderId}'.replaceAll('{format}', 'json').replaceAll('{' + 'orderId' + '}', orderId.toString()); + final path = '/store/order/{orderId}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'orderId' + '}', orderId.toString()); Object postBody; @@ -208,10 +208,13 @@ class StoreApi { /// ID of pet that needs to be fetched Future getOrderById(int orderId) async { final response = await getOrderByIdWithHttpInfo(orderId); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return apiClient.deserialize(_decodeBodyBytes(response), 'Order') as Order; } return null; @@ -228,7 +231,7 @@ class StoreApi { Future placeOrderWithHttpInfo(Order body) async { // Verify required params are set. if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } final path = '/store/order'.replaceAll('{format}', 'json'); @@ -276,10 +279,13 @@ class StoreApi { /// order placed for purchasing the pet Future placeOrder(Order body) async { final response = await placeOrderWithHttpInfo(body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return apiClient.deserialize(_decodeBodyBytes(response), 'Order') as Order; } return null; diff --git a/samples/client/petstore/dart2/petstore_client_lib/lib/api/user_api.dart b/samples/client/petstore/dart2/petstore_client_lib/lib/api/user_api.dart index e6c8c89d449..575660e3444 100644 --- a/samples/client/petstore/dart2/petstore_client_lib/lib/api/user_api.dart +++ b/samples/client/petstore/dart2/petstore_client_lib/lib/api/user_api.dart @@ -28,7 +28,7 @@ class UserApi { Future createUserWithHttpInfo(User body) async { // Verify required params are set. if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } final path = '/user'.replaceAll('{format}', 'json'); @@ -78,12 +78,9 @@ class UserApi { /// Created user object Future createUser(User body) async { final response = await createUserWithHttpInfo(body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Creates list of users with given input array @@ -97,7 +94,7 @@ class UserApi { Future createUsersWithArrayInputWithHttpInfo(List body) async { // Verify required params are set. if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } final path = '/user/createWithArray'.replaceAll('{format}', 'json'); @@ -145,12 +142,9 @@ class UserApi { /// List of user object Future createUsersWithArrayInput(List body) async { final response = await createUsersWithArrayInputWithHttpInfo(body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Creates list of users with given input array @@ -164,7 +158,7 @@ class UserApi { Future createUsersWithListInputWithHttpInfo(List body) async { // Verify required params are set. if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } final path = '/user/createWithList'.replaceAll('{format}', 'json'); @@ -212,12 +206,9 @@ class UserApi { /// List of user object Future createUsersWithListInput(List body) async { final response = await createUsersWithListInputWithHttpInfo(body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Delete user @@ -233,10 +224,11 @@ class UserApi { Future deleteUserWithHttpInfo(String username) async { // Verify required params are set. if (username == null) { - throw ApiException(400, 'Missing required param: username'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: username'); } - final path = '/user/{username}'.replaceAll('{format}', 'json').replaceAll('{' + 'username' + '}', username.toString()); + final path = '/user/{username}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'username' + '}', username.toString()); Object postBody; @@ -283,12 +275,9 @@ class UserApi { /// The name that needs to be deleted Future deleteUser(String username) async { final response = await deleteUserWithHttpInfo(username); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Get user by user name @@ -302,10 +291,11 @@ class UserApi { Future getUserByNameWithHttpInfo(String username) async { // Verify required params are set. if (username == null) { - throw ApiException(400, 'Missing required param: username'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: username'); } - final path = '/user/{username}'.replaceAll('{format}', 'json').replaceAll('{' + 'username' + '}', username.toString()); + final path = '/user/{username}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'username' + '}', username.toString()); Object postBody; @@ -350,10 +340,13 @@ class UserApi { /// The name that needs to be fetched. Use user1 for testing. Future getUserByName(String username) async { final response = await getUserByNameWithHttpInfo(username); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return apiClient.deserialize(_decodeBodyBytes(response), 'User') as User; } return null; @@ -373,10 +366,10 @@ class UserApi { Future loginUserWithHttpInfo(String username, String password) async { // Verify required params are set. if (username == null) { - throw ApiException(400, 'Missing required param: username'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: username'); } if (password == null) { - throw ApiException(400, 'Missing required param: password'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: password'); } final path = '/user/login'.replaceAll('{format}', 'json'); @@ -429,10 +422,13 @@ class UserApi { /// The password for login in clear text Future loginUser(String username, String password) async { final response = await loginUserWithHttpInfo(username, password); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body != null && response.statusCode != HttpStatus.noContent) { return apiClient.deserialize(_decodeBodyBytes(response), 'String') as String; } return null; @@ -442,8 +438,6 @@ class UserApi { /// /// Note: This method returns the HTTP [Response]. Future logoutUserWithHttpInfo() async { - // Verify required params are set. - final path = '/user/logout'.replaceAll('{format}', 'json'); Object postBody; @@ -484,12 +478,9 @@ class UserApi { /// Logs out current logged in user session Future logoutUser() async { final response = await logoutUserWithHttpInfo(); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } /// Updated user @@ -508,13 +499,14 @@ class UserApi { Future updateUserWithHttpInfo(String username, User body) async { // Verify required params are set. if (username == null) { - throw ApiException(400, 'Missing required param: username'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: username'); } if (body == null) { - throw ApiException(400, 'Missing required param: body'); + throw ApiException(HttpStatus.badRequest, 'Missing required param: body'); } - final path = '/user/{username}'.replaceAll('{format}', 'json').replaceAll('{' + 'username' + '}', username.toString()); + final path = '/user/{username}'.replaceAll('{format}', 'json') + .replaceAll('{' + 'username' + '}', username.toString()); Object postBody = body; @@ -564,11 +556,8 @@ class UserApi { /// Updated user object Future updateUser(String username, User body) async { final response = await updateUserWithHttpInfo(username, body); - if (response.statusCode >= 400) { + if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, _decodeBodyBytes(response)); } - if (response.body != null) { - } - return; } } diff --git a/samples/client/petstore/dart2/petstore_client_lib/lib/api_client.dart b/samples/client/petstore/dart2/petstore_client_lib/lib/api_client.dart index 2d86d6f338f..af9d4ec7a69 100644 --- a/samples/client/petstore/dart2/petstore_client_lib/lib/api_client.dart +++ b/samples/client/petstore/dart2/petstore_client_lib/lib/api_client.dart @@ -118,16 +118,16 @@ class ApiClient { case 'GET': return await _client.get(url, headers: nullableHeaderParams); } } on SocketException catch (e, trace) { - throw ApiException.withInner(400, 'Socket operation failed: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'Socket operation failed: $method $path', e, trace); } on TlsException catch (e, trace) { - throw ApiException.withInner(400, 'TLS/SSL communication failed: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'TLS/SSL communication failed: $method $path', e, trace); } on IOException catch (e, trace) { - throw ApiException.withInner(400, 'I/O operation failed: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'I/O operation failed: $method $path', e, trace); } on Exception catch (e, trace) { - throw ApiException.withInner(400, 'Exception occurred: $method $path', e, trace); + throw ApiException.withInner(HttpStatus.badRequest, 'Exception occurred: $method $path', e, trace); } - throw ApiException(400, 'Invalid HTTP operation: $method $path'); + throw ApiException(HttpStatus.badRequest, 'Invalid HTTP operation: $method $path'); } dynamic _deserialize(dynamic value, String targetType, {bool growable}) { @@ -176,9 +176,9 @@ class ApiClient { break; } } on Exception catch (e, stack) { - throw ApiException.withInner(500, 'Exception during deserialization.', e, stack); + throw ApiException.withInner(HttpStatus.internalServerError, 'Exception during deserialization.', e, stack); } - throw ApiException(500, 'Could not find a suitable class for deserialization'); + throw ApiException(HttpStatus.internalServerError, 'Could not find a suitable class for deserialization'); } /// Update query and header parameters based on authentication settings. diff --git a/samples/client/petstore/dart2/petstore_client_lib/lib/api_helper.dart b/samples/client/petstore/dart2/petstore_client_lib/lib/api_helper.dart index 4eed380b500..5ae7b8d6de7 100644 --- a/samples/client/petstore/dart2/petstore_client_lib/lib/api_helper.dart +++ b/samples/client/petstore/dart2/petstore_client_lib/lib/api_helper.dart @@ -55,7 +55,7 @@ String parameterToString(dynamic value) { /// content type. Otherwise, returns the decoded body as decoded by dart:http package. String _decodeBodyBytes(Response response) { final contentType = response.headers['content-type']; - return contentType != null && contentType.contains('application/json') - ? utf8.decode(response.bodyBytes) + return contentType != null && contentType.toLowerCase().startsWith('application/json') + ? response.bodyBytes == null ? null : utf8.decode(response.bodyBytes) : response.body; }