From fb078e124460c8478c0874bb4727ca9db2bd5168 Mon Sep 17 00:00:00 2001 From: Ben Yarger Date: Wed, 16 Aug 2023 12:01:03 -0700 Subject: [PATCH 1/2] Support Charset encoding specification during response parsing via NSTServiceWrapperProcessor (v1.1.10). --- .../ebay/nst/NSTServiceWrapperProcessor.java | 17 ++++++++- .../service/protocol/http/NSTHttpClient.java | 16 +++++++++ .../protocol/http/NSTHttpClientImpl.java | 20 ++++++++--- .../nst/NSTServiceWrapperProcessorTest.java | 23 ++++++++++-- .../protocol/http/NSTHttpClientImplTest.java | 36 +++++++++++++++++-- pom.xml | 2 +- 6 files changed, 101 insertions(+), 13 deletions(-) diff --git a/NST/src/main/java/com/ebay/nst/NSTServiceWrapperProcessor.java b/NST/src/main/java/com/ebay/nst/NSTServiceWrapperProcessor.java index f5cae11..9002315 100644 --- a/NST/src/main/java/com/ebay/nst/NSTServiceWrapperProcessor.java +++ b/NST/src/main/java/com/ebay/nst/NSTServiceWrapperProcessor.java @@ -2,8 +2,11 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; +import java.util.Objects; import com.ebay.runtime.arguments.DisableConsoleLog; import org.json.JSONObject; @@ -23,12 +26,15 @@ import com.ebay.service.protocol.http.NSTHttpResponse; import com.ebay.utility.service.ServiceUtil; +import javax.validation.constraints.NotNull; + public final class NSTServiceWrapperProcessor { private boolean disableSchemaValidation = false; private boolean disableRequestResponseLogging = false; private boolean confirmSuccess = true; private NSTHttpClient client; + private Charset responseParsingCharset = StandardCharsets.UTF_8; /** * Creates a new service process with the default HttpUrlConnection used for @@ -138,6 +144,15 @@ public NSTServiceWrapperProcessor resetConfirmSuccess() { return this; } + /** + * Set the response parsing charset to use. Default is UTF_8. + * @param responseParsingCharset Response parsing Charset to use when parsing the response. + */ + public void setResponseParsingCharset(@NotNull Charset responseParsingCharset) { + Objects.requireNonNull(responseParsingCharset, "Response parsing charset MUST NOT be null."); + this.responseParsingCharset = responseParsingCharset; + } + /** * Send the request and get back the response JSON object. * @@ -292,7 +307,7 @@ protected void logRequestDetailsToConsole(NSTServiceWrapper serviceWrapper, diff --git a/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClient.java b/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClient.java index 4edbc86..14b710a 100644 --- a/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClient.java +++ b/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClient.java @@ -1,7 +1,23 @@ package com.ebay.service.protocol.http; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + public interface NSTHttpClient { + /** + * Send the request and return the response. Uses the default Charset specified by the implementation. + * @param request Request to send. + * @return Response model. + */ public Response sendRequest(Request request); + + /** + * Send the request and return the response. + * @param request Request to send. + * @param readResponseCharSet Character set to use when parsing the response payload. Recommend sourcing from java.nio.charset.StandardCharsets. + * @return Response model. + */ + public Response sendRequest(Request request, Charset readResponseCharSet); } diff --git a/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClientImpl.java b/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClientImpl.java index 3beff72..5ef7538 100644 --- a/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClientImpl.java +++ b/NST/src/main/java/com/ebay/service/protocol/http/NSTHttpClientImpl.java @@ -6,6 +6,8 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -19,14 +21,20 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import javax.validation.constraints.NotNull; import com.ebay.nst.NstRequestType; public class NSTHttpClientImpl implements NSTHttpClient { - @SuppressWarnings("fallthrough") @Override public NSTHttpResponse sendRequest(NSTHttpRequest request) { + return sendRequest(request, StandardCharsets.UTF_8); + } + + @SuppressWarnings("fallthrough") + @Override + public NSTHttpResponse sendRequest(NSTHttpRequest request, Charset readResponseCharSet) { Objects.requireNonNull(request, "Request MUST NOT be null."); @@ -78,7 +86,7 @@ public NSTHttpResponse sendRequest(NSTHttpRequest request) { try { OutputStream os = connection.getOutputStream(); - byte[] input = payload.getBytes("utf-8"); + byte[] input = payload.getBytes(readResponseCharSet); os.write(input, 0, input.length); } catch (Exception e) { throw new RuntimeException(String.format("Exception occurred getting %s data from the connection.", requestType.name()), e); @@ -97,7 +105,7 @@ public NSTHttpResponse sendRequest(NSTHttpRequest request) { NSTHttpResponse response; try { - response = parseResponse(connection); + response = parseResponse(connection, readResponseCharSet); } catch (IOException e) { throw new RuntimeException("Exception occurred parsing response data.", e); } @@ -117,12 +125,14 @@ public NSTHttpResponse sendRequest(NSTHttpRequest request) { * @return Parsed response body. * @throws IOException IO Error. */ - protected final NSTHttpResponse parseResponse(HttpURLConnection connection) throws IOException { + protected final NSTHttpResponse parseResponse(HttpURLConnection connection, @NotNull Charset readResponseCharSet) throws IOException { NSTHttpResponseImpl response = new NSTHttpResponseImpl(); if (connection == null) { return response; + } if (readResponseCharSet == null) { + return response; } response.setResponseCode(connection.getResponseCode()); @@ -142,7 +152,7 @@ protected final NSTHttpResponse parseResponse(HttpURLConnection connection) thro } } - BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), readResponseCharSet)); String inputLine; StringBuffer content = new StringBuffer(); while ((inputLine = in.readLine()) != null) { diff --git a/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java b/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java index a484b8e..c1e77b5 100644 --- a/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java +++ b/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java @@ -25,6 +25,8 @@ import java.io.*; import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -244,7 +246,7 @@ public void testSendRequestAndGetJsonResponse() throws Exception { when(response.getResponseCode()).thenReturn(200); NSTHttpClient client = mock(NSTHttpClient.class); - when(client.sendRequest(Mockito.any(NSTHttpRequest.class))).thenReturn(response); + when(client.sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class))).thenReturn(response); processor = new NSTServiceWrapperProcessor(client); JSONObject actualJsonObject = processor.sendRequestAndGetJSONResponse(nstServiceWrapper); @@ -632,14 +634,29 @@ public void getServiceWrapperNameWithUniqueWrapperName() { public void sendRequest() throws Exception { NSTHttpClient client = mock(NSTHttpClient.class); - when(client.sendRequest(Mockito.any(NSTHttpRequest.class))).thenReturn(new NSTHttpResponseImpl()); + when(client.sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class))).thenReturn(new NSTHttpResponseImpl()); NSTHttpRequest request = mock(NSTHttpRequest.class); processor = new NSTServiceWrapperProcessor(client); processor.sendRequest(request); - verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class)); + verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class)); + } + + @Test + public void sendRequestWithAlternateCharacterSetUsedToParseResponse() throws Exception { + + NSTHttpClient client = mock(NSTHttpClient.class); + when(client.sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class))).thenReturn(new NSTHttpResponseImpl()); + + NSTHttpRequest request = mock(NSTHttpRequest.class); + + processor = new NSTServiceWrapperProcessor(client); + processor.setResponseParsingCharset(StandardCharsets.ISO_8859_1); + processor.sendRequest(request); + + verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class)); } @Test diff --git a/NST/src/test/java/com/ebay/service/protocol/http/NSTHttpClientImplTest.java b/NST/src/test/java/com/ebay/service/protocol/http/NSTHttpClientImplTest.java index d68844f..8cc1a70 100644 --- a/NST/src/test/java/com/ebay/service/protocol/http/NSTHttpClientImplTest.java +++ b/NST/src/test/java/com/ebay/service/protocol/http/NSTHttpClientImplTest.java @@ -17,6 +17,7 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -155,7 +156,16 @@ public void delete() throws Exception { @Test public void nullConnection() throws Exception { - NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(null); + NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(null, StandardCharsets.UTF_8); + assertThat(actual.getPayload(), is(nullValue())); + assertThat(actual.getHeaders(), is(anEmptyMap())); + assertThat(actual.getResponseCode(), is(equalTo(0))); + } + + @Test + public void nullCharsetUsedToParseResponse() throws Exception { + + NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection, null); assertThat(actual.getPayload(), is(nullValue())); assertThat(actual.getHeaders(), is(anEmptyMap())); assertThat(actual.getResponseCode(), is(equalTo(0))); @@ -165,7 +175,7 @@ public void nullConnection() throws Exception { public void nullConnectionHeaderFields() throws Exception { when(connection.getHeaderFields()).thenReturn(null); - NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection); + NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection, StandardCharsets.UTF_8); assertThat(actual.getHeaders(), is(anEmptyMap())); } @@ -178,9 +188,29 @@ public void fullResponse() throws Exception { InputStream targetStream = new ByteArrayInputStream(payload.getBytes()); when(connection.getInputStream()).thenReturn(targetStream); - NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection); + NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection, StandardCharsets.UTF_8); assertThat(actual.getPayload(), is(equalTo(payload))); assertThat(actual.getHeaders(), is(equalTo(expectedHeaders))); assertThat(actual.getResponseCode(), is(equalTo(200))); } + + @Test + public void parseResponseWithExtendedCharacterSetUsingIsoCharset() throws Exception { + InputStream targetStream = new ByteArrayInputStream("©".getBytes(StandardCharsets.UTF_8)); + when(connection.getInputStream()).thenReturn(targetStream); + when(connection.getResponseCode()).thenReturn(200); + when(connection.getHeaderFields()).thenReturn(null); + NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection, StandardCharsets.ISO_8859_1); + assertThat(actual.getPayload(), is(equalTo("©"))); + } + + @Test + public void parseResponseWithExtendedCharacterSetUsingUtf8Charset() throws Exception { + InputStream targetStream = new ByteArrayInputStream("©".getBytes(StandardCharsets.UTF_8)); + when(connection.getInputStream()).thenReturn(targetStream); + when(connection.getResponseCode()).thenReturn(200); + when(connection.getHeaderFields()).thenReturn(null); + NSTHttpResponseImpl actual = (NSTHttpResponseImpl) implementation.parseResponse(connection, StandardCharsets.UTF_8); + assertThat(actual.getPayload(), is(equalTo("©"))); + } } diff --git a/pom.xml b/pom.xml index 07e940c..914f03e 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 3.6.0 2.9 UTF-8 - 1.1.9 + 1.1.10 7.5 true From 9818c7704069d65d6263022a796167f6f90884a9 Mon Sep 17 00:00:00 2001 From: Ben Yarger Date: Wed, 16 Aug 2023 13:55:53 -0700 Subject: [PATCH 2/2] Checking the default Charset value and the explicitly set one in the unit tests. --- .../java/com/ebay/nst/NSTServiceWrapperProcessorTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java b/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java index c1e77b5..e37968a 100644 --- a/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java +++ b/NST/src/test/java/com/ebay/nst/NSTServiceWrapperProcessorTest.java @@ -35,6 +35,7 @@ import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import static org.testng.AssertJUnit.fail; @@ -641,7 +642,7 @@ public void sendRequest() throws Exception { processor = new NSTServiceWrapperProcessor(client); processor.sendRequest(request); - verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class)); + verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class), eq(StandardCharsets.UTF_8)); } @Test @@ -656,7 +657,7 @@ public void sendRequestWithAlternateCharacterSetUsedToParseResponse() throws Exc processor.setResponseParsingCharset(StandardCharsets.ISO_8859_1); processor.sendRequest(request); - verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class), Mockito.any(Charset.class)); + verify(client, times(1)).sendRequest(Mockito.any(NSTHttpRequest.class), eq(StandardCharsets.ISO_8859_1)); } @Test