From e9c4990e58a729a2fefb1d6b719cb8cf6d318084 Mon Sep 17 00:00:00 2001 From: Egor Cherniak Date: Wed, 24 Jul 2024 20:01:01 +0300 Subject: [PATCH] Encode non-ascii text (#79) * Encode non-ascii text * Add test --- .../adapter/common/mapper/ErrorMapping.java | 30 ++++++++++++++++--- .../common/mapper/ErrorMappingTest.java | 7 +++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/vality/adapter/common/mapper/ErrorMapping.java b/src/main/java/dev/vality/adapter/common/mapper/ErrorMapping.java index cbb7b20..fe0e758 100644 --- a/src/main/java/dev/vality/adapter/common/mapper/ErrorMapping.java +++ b/src/main/java/dev/vality/adapter/common/mapper/ErrorMapping.java @@ -13,13 +13,16 @@ import dev.vality.woody.api.flow.error.*; import java.io.IOException; import java.io.InputStream; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.StandardCharsets; +import java.util.*; public class ErrorMapping { private static final String DEFAULT_PATTERN_REASON = "'%s' - '%s'"; + private static final String DEFAULT_BASE64_PREFIX = "base64:"; + private static final CharsetEncoder ASCII_ENCODER = StandardCharsets.US_ASCII.newEncoder(); /** * Pattern for reason failure @@ -137,7 +140,26 @@ public class ErrorMapping { code, description, state); var errorDefinition = new WErrorDefinition(WErrorSource.INTERNAL); errorDefinition.setErrorType(WErrorType.UNEXPECTED_ERROR); - errorDefinition.setErrorReason(String.format("code = %s, description = %s", code, description)); + errorDefinition.setErrorReason(String.format("code = %s, description = %s", + makeCompatibleWithHttpHeader(code), + makeCompatibleWithHttpHeader(description))); return new WRuntimeException(errorMessage, errorDefinition); } + + private String makeCompatibleWithHttpHeader(String text) { + if (text == null || !containsNonAsciiSymbols(text)) { + return text; + } + return DEFAULT_BASE64_PREFIX + + Base64.getEncoder().withoutPadding().encodeToString(text.getBytes(StandardCharsets.UTF_8)); + } + + private boolean containsNonAsciiSymbols(String text) { + for (char c : text.toCharArray()) { + if (!ASCII_ENCODER.canEncode(c)) { + return true; + } + } + return false; + } } diff --git a/src/test/java/dev/vality/adapter/common/mapper/ErrorMappingTest.java b/src/test/java/dev/vality/adapter/common/mapper/ErrorMappingTest.java index b64af64..6d75370 100644 --- a/src/test/java/dev/vality/adapter/common/mapper/ErrorMappingTest.java +++ b/src/test/java/dev/vality/adapter/common/mapper/ErrorMappingTest.java @@ -33,6 +33,13 @@ public class ErrorMappingTest { errorMappingFull.mapFailure("00001").toString()); } + @Test + public void nonAsciiTest() { + var errorMappingFull = new ErrorMapping("'%s' - '%s'", List.of()); + var exception = assertThrows(WRuntimeException.class, () -> errorMappingFull.mapFailure("ы")); + assertEquals("code = base64:0Ys, description = null", exception.getErrorDefinition().getErrorReason()); + } + @Test public void testNullDesc() { Error error = new Error();