Skip to content

Commit

Permalink
fix: force to decode as utf-8 when header contains application/json t…
Browse files Browse the repository at this point in the history
…o avoid text garbling. (OpenAPITools#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: dart-lang/http#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.
  • Loading branch information
cimadai authored and wing328 committed Jan 9, 2019
1 parent 637d60d commit fd12cf3
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

0 comments on commit fd12cf3

Please sign in to comment.