diff --git a/lib/src/utils/http_helper.dart b/lib/src/utils/http_helper.dart index c5492fbb76..ce92c7137b 100644 --- a/lib/src/utils/http_helper.dart +++ b/lib/src/utils/http_helper.dart @@ -96,7 +96,7 @@ class HttpHelper { } } - http.Response response = await http.post( + return http.post( uri, headers: _buildHeaders( user: user, @@ -105,7 +105,6 @@ class HttpHelper { ), body: addUserAgentParameters(body), ); - return response; } static const String userInfoForTest = 'off:off'; @@ -214,7 +213,9 @@ class HttpHelper { headers.addAll({ 'Accept': 'application/json', 'User-Agent': OpenFoodAPIConfiguration.userAgent!.toValueString(), - 'From': OpenFoodAPIConfiguration.getUser(user)?.userId ?? FROM, + 'From': _getSafeString( + OpenFoodAPIConfiguration.getUser(user)?.userId ?? FROM, + ), }); final bool isTestModeActive = uriHelper.isTestMode; @@ -254,4 +255,27 @@ class HttpHelper { rethrow; } } + + /// Returns true if the [input] string is ISO-8859-1 encoded. + static bool _isIso88591(final String input) { + try { + latin1.encode(input); + return true; + } catch (e) { + return false; + } + } + + /// Returns the [input] string if ISO-8859-1 encoded, or a safer version of it + /// + /// Used for HTTP headers, that do not accept any other charset. + /// Here instead of encoding systematically, we keep ISO-8859-1 inputs and + /// only encode the other "problematic" inputs. + /// cf. https://github.com/openfoodfacts/openfoodfacts-dart/issues/829 + static String _getSafeString(final String input) { + if (_isIso88591(input)) { + return input; + } + return base64Encode(utf8.encode(input)); + } } diff --git a/test/user_management_test_test_env.dart b/test/user_management_test_test_env.dart index 31aab14f10..44bb309875 100644 --- a/test/user_management_test_test_env.dart +++ b/test/user_management_test_test_env.dart @@ -61,6 +61,15 @@ void main() { expect(status?.successful, false); expect(status?.statusVerbose, 'user not signed-in'); }); + + test('Login with problematic charset', () async { + final LoginStatus? status = await OpenFoodAPIClient.login2( + User(userId: 'លីវយី', password: ''), + uriHelper: uriHelper, + ); + expect(status?.successful, false); + expect(status?.statusVerbose, 'user not signed-in'); + }); }); }