From fd12cf3c2c7b54d0d01a84fa1010b78ab9e5ce27 Mon Sep 17 00:00:00 2001 From: Daisuke Shimada Date: Wed, 9 Jan 2019 12:08:35 +0900 Subject: [PATCH] fix: force to decode as utf-8 when header contains application/json to avoid text garbling. (#1700) * fix: force to decode as utf-8 when header contains application/json to avoid text garbling. The original processing is using `response.body` to deserialize as json. However, this is decoded by latin1 if the header contains only "application/json" instead of "application/json; charset=utf-8". Because of this behavior, if the response body is encoded UTF-8 but the headers doesn't contain charset, the body will garbling. cf: https://github.com/dart-lang/http/issues/175 Since playframework 2.6 returns "Content-Type: application/json" without "charset=utf-8", I changed this parsing algolithm. * fix: force to decode as utf-8 when header contains application/json to avoid text garbling on error. --- .../src/main/resources/dart/api.mustache | 8 ++++---- .../src/main/resources/dart/api_helper.mustache | 12 ++++++++++++ .../src/main/resources/dart2/api.mustache | 8 ++++---- .../src/main/resources/dart2/api_helper.mustache | 12 ++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/dart/api.mustache b/modules/openapi-generator/src/main/resources/dart/api.mustache index 6ed091fc7ee7..373ce2508b3e 100644 --- a/modules/openapi-generator/src/main/resources/dart/api.mustache +++ b/modules/openapi-generator/src/main/resources/dart/api.mustache @@ -89,22 +89,22 @@ class {{classname}} { authNames); if(response.statusCode >= 400) { - throw new ApiException(response.statusCode, response.body); + throw new ApiException(response.statusCode, _decodeBodyBytes(response)); } else if(response.body != null) { {{#isListContainer}} {{#returnType}} - return (apiClient.deserialize(response.body, '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList(); + return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList(); {{/returnType}} {{/isListContainer}} {{^isListContainer}} {{#isMapContainer}} {{#returnType}} - return new {{{returnType}}}.from(apiClient.deserialize(response.body, '{{{returnType}}}')); + return new {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}')); {{/returnType}}; {{/isMapContainer}} {{^isMapContainer}} {{#returnType}} - return apiClient.deserialize(response.body, '{{{returnType}}}') as {{{returnType}}}; + return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}}; {{/returnType}} {{/isMapContainer}} {{/isListContainer}} diff --git a/modules/openapi-generator/src/main/resources/dart/api_helper.mustache b/modules/openapi-generator/src/main/resources/dart/api_helper.mustache index 3929fa2b7628..73b2585b1b45 100644 --- a/modules/openapi-generator/src/main/resources/dart/api_helper.mustache +++ b/modules/openapi-generator/src/main/resources/dart/api_helper.mustache @@ -50,3 +50,15 @@ String parameterToString(dynamic value) { return value.toString(); } } + +/// Returns the decoded body by utf-8 if application/json with the given headers. +/// Else, returns the decoded body by default algorithm of dart:http. +/// Because avoid to text garbling when header only contains "application/json" without "; charset=utf-8". +String _decodeBodyBytes(Response response) { + var contentType = response.headers['content-type']; + if (contentType != null && contentType.contains("application/json")) { + return utf8.decode(response.bodyBytes); + } else { + return response.body; + } +} diff --git a/modules/openapi-generator/src/main/resources/dart2/api.mustache b/modules/openapi-generator/src/main/resources/dart2/api.mustache index 76797fa2ddc3..3a29f01f8276 100644 --- a/modules/openapi-generator/src/main/resources/dart2/api.mustache +++ b/modules/openapi-generator/src/main/resources/dart2/api.mustache @@ -89,22 +89,22 @@ class {{classname}} { authNames); if(response.statusCode >= 400) { - throw new ApiException(response.statusCode, response.body); + throw new ApiException(response.statusCode, _decodeBodyBytes(response)); } else if(response.body != null) { {{#isListContainer}} {{#returnType}} - return (apiClient.deserialize(response.body, '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList(); + return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList(); {{/returnType}} {{/isListContainer}} {{^isListContainer}} {{#isMapContainer}} {{#returnType}} - return new {{{returnType}}}.from(apiClient.deserialize(response.body, '{{{returnType}}}')); + return new {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}')); {{/returnType}}; {{/isMapContainer}} {{^isMapContainer}} {{#returnType}} - return apiClient.deserialize(response.body, '{{{returnType}}}') as {{{returnType}}}; + return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}}; {{/returnType}} {{/isMapContainer}} {{/isListContainer}} 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 1e554bede4b3..7027f30a5b60 100644 --- a/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache +++ b/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache @@ -50,3 +50,15 @@ String parameterToString(dynamic value) { return value.toString(); } } + +/// Returns the decoded body by utf-8 if application/json with the given headers. +/// Else, returns the decoded body by default algorithm of dart:http. +/// Because avoid to text garbling when header only contains "application/json" without "; charset=utf-8". +String _decodeBodyBytes(Response response) { + var contentType = response.headers['content-type']; + if (contentType != null && contentType.contains("application/json")) { + return utf8.decode(response.bodyBytes); + } else { + return response.body; + } +}