From 55492379c931c2a16df1520d10e6fed83aa0ea8e Mon Sep 17 00:00:00 2001 From: ramari16 Date: Fri, 31 Jan 2025 14:51:30 -0500 Subject: [PATCH] ALS-8239: Fix PFB encoding issues (#217) --- .../AggregateDataSharingResourceRS.java | 3 ++- .../passthru/PassThroughResourceRS.java | 18 +++++++++--------- .../passthru/PassThroughResourceRSTest.java | 11 +++++------ .../avillach/service/ResourceWebClient.java | 14 +++++++------- .../service/ResourceWebClientTest.java | 6 +++--- .../dbmi/avillach/util/HttpClientUtil.java | 17 ++++++++++++++--- 6 files changed, 40 insertions(+), 29 deletions(-) diff --git a/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/src/main/java/edu/harvard/hms/dbmi/avillach/AggregateDataSharingResourceRS.java b/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/src/main/java/edu/harvard/hms/dbmi/avillach/AggregateDataSharingResourceRS.java index e3e7d7ad..c280cfce 100644 --- a/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/src/main/java/edu/harvard/hms/dbmi/avillach/AggregateDataSharingResourceRS.java +++ b/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/src/main/java/edu/harvard/hms/dbmi/avillach/AggregateDataSharingResourceRS.java @@ -30,6 +30,7 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -207,7 +208,7 @@ public Response queryResult(@PathParam("resourceQueryId") UUID queryId, QueryReq checkQuery(resultRequest); HttpResponse response = postRequest(resultRequest, "/query/" + queryId + "/result"); try { - String responseBody = httpClientUtil.readObjectFromResponse(response); + String responseBody = httpClientUtil.readObjectFromResponse(response, StandardCharsets.UTF_8); return Response.ok(responseBody).build(); } finally { HttpClientUtil.closeHttpResponse(response); diff --git a/pic-sure-resources/pic-sure-passthrough-resource/src/main/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRS.java b/pic-sure-resources/pic-sure-passthrough-resource/src/main/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRS.java index ecf06b61..c2f8b4f8 100644 --- a/pic-sure-resources/pic-sure-passthrough-resource/src/main/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRS.java +++ b/pic-sure-resources/pic-sure-passthrough-resource/src/main/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRS.java @@ -1,6 +1,7 @@ package edu.harvard.hms.dbmi.avillach.resource.passthru; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.UUID; import javax.inject.Inject; @@ -13,7 +14,6 @@ import org.apache.http.HttpResponse; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; -import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +69,7 @@ public PassThroughResourceRS(ApplicationProperties properties, HttpClientUtil ht public ResourceInfo info(QueryRequest infoRequest) { String pathName = "/info"; - HttpResponse response = null; + HttpResponse response = null; try { QueryRequest chainRequest = new GeneralQueryRequest(); if (infoRequest != null) { @@ -101,8 +101,8 @@ public ResourceInfo info(QueryRequest infoRequest) { logger.error(e.getMessage()); throw new ProtocolException(ProtocolException.INCORRECTLY_FORMATTED_REQUEST); } finally { - closeHttpResponse(response); - } + closeHttpResponse(response); + } } @POST @@ -154,7 +154,7 @@ public Response queryResult(@PathParam("resourceQueryId") String queryId, QueryR String pathName = "/query/" + queryId + "/result"; - HttpResponse response = null; + HttpResponse response = null; try { QueryRequest chainRequest = new GeneralQueryRequest(); chainRequest.setQuery(resultRequest.getQuery()); @@ -164,8 +164,8 @@ public Response queryResult(@PathParam("resourceQueryId") String queryId, QueryR String payload = objectMapper.writeValueAsString(chainRequest); response = httpClient .retrievePostResponse(httpClient.composeURL(properties.getTargetPicsureUrl(), pathName), createAuthHeader(), payload); - String content = httpClient.readObjectFromResponse(response); - if (response.getStatusLine().getStatusCode() != 200) { + byte[] content = httpClient.readBytesFromResponse(response); + if (response.getStatusLine().getStatusCode() != 200) { logger.error( "{}{} calling resource with id {} did not return a 200: {} {} ", properties.getTargetPicsureUrl(), pathName, chainRequest.getResourceUUID(), response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase() @@ -180,8 +180,8 @@ public Response queryResult(@PathParam("resourceQueryId") String queryId, QueryR logger.error(e.getMessage()); throw new ProtocolException(ProtocolException.INCORRECTLY_FORMATTED_REQUEST); } finally { - closeHttpResponse(response); - } + closeHttpResponse(response); + } } @POST diff --git a/pic-sure-resources/pic-sure-passthrough-resource/src/test/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRSTest.java b/pic-sure-resources/pic-sure-passthrough-resource/src/test/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRSTest.java index 1c8daf44..8cb54490 100644 --- a/pic-sure-resources/pic-sure-passthrough-resource/src/test/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRSTest.java +++ b/pic-sure-resources/pic-sure-passthrough-resource/src/test/java/edu/harvard/hms/dbmi/avillach/resource/passthru/PassThroughResourceRSTest.java @@ -1,9 +1,7 @@ package edu.harvard.hms.dbmi.avillach.resource.passthru; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -139,7 +137,8 @@ void testQueryResult() throws Exception { when(httpResponse.getStatusLine()).thenReturn(statusLine); when(httpResponse.getEntity()).thenReturn(httpResponseEntity); when(httpClient.retrievePostResponse(anyString(), any(Header[].class), anyString())).thenReturn(httpResponse); - when(httpClient.readObjectFromResponse(any(HttpResponse.class))).thenReturn("4"); + byte[] byteResponse = {101}; + when(httpClient.readBytesFromResponse(any(HttpResponse.class))).thenReturn(byteResponse); assertThrows(ProtocolException.class, () -> { resource.queryResult("", null); @@ -167,7 +166,7 @@ void testQueryResult() throws Exception { when(httpResponse.getEntity()).thenReturn(httpResponseEntity); GeneralQueryRequest queryRequest = newQueryRequest(null); javax.ws.rs.core.Response returnVal = resource.queryResult(queryId.toString(), queryRequest); - assertEquals("4", returnVal.getEntity()); + assertArrayEquals(byteResponse, (byte[]) returnVal.getEntity()); // assertEquals(resultId, returnVal.getHeaderString("resultId")); } diff --git a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java index 0ac54062..13d2f968 100644 --- a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java +++ b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java @@ -14,15 +14,15 @@ import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; -import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.enterprise.context.ApplicationScoped; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; -import java.io.IOException; +import java.io.*; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.util.Map; import static edu.harvard.dbmi.avillach.util.HttpClientUtil.closeHttpResponse; @@ -240,7 +240,7 @@ public Response queryResult(String rsURL, String queryId, QueryRequest queryRequ HttpClientUtil.composeURL(rsURL, pathName), createHeaders(queryRequest.getResourceCredentials()), body ); - String content = httpClientUtil.readObjectFromResponse(resourcesResponse); + byte[] content = httpClientUtil.readBytesFromResponse(resourcesResponse); if (resourcesResponse.getStatusLine().getStatusCode() != 200) { logger.error("ResourceRS did not return a 200"); HttpClientUtil.throwResponseError(resourcesResponse, rsURL); @@ -281,7 +281,7 @@ public Response queryResultSignedUrl(String rsURL, String queryId, QueryRequest httpClientUtil.throwResponseError(resourcesResponse, rsURL); } - String content = httpClientUtil.readObjectFromResponse(resourcesResponse); + String content = httpClientUtil.readObjectFromResponse(resourcesResponse, StandardCharsets.UTF_8); return Response.ok(content).build(); } catch (JsonProcessingException e) { logger.error("Unable to encode resource credentials"); @@ -311,7 +311,7 @@ public Response queryFormat(String rsURL, QueryRequest queryRequest) { httpClientUtil.composeURL(rsURL, pathName), createHeaders(queryRequest.getResourceCredentials()), body ); - String content = httpClientUtil.readObjectFromResponse(resourcesResponse); + String content = httpClientUtil.readObjectFromResponse(resourcesResponse, StandardCharsets.UTF_8); int status = resourcesResponse.getStatusLine().getStatusCode(); if (status != 200) { logger.error("Query format request did not return a 200: {}", resourcesResponse.getStatusLine().getStatusCode()); @@ -360,7 +360,7 @@ public Response querySync(String rsURL, QueryRequest queryRequest, String reques throwError(resourcesResponse, rsURL); } - String content = httpClientUtil.readObjectFromResponse(resourcesResponse); + String content = httpClientUtil.readObjectFromResponse(resourcesResponse, StandardCharsets.UTF_8); if (resourcesResponse.containsHeader(QUERY_METADATA_FIELD)) { Header metadataHeader = ((Header[]) resourcesResponse.getHeaders(QUERY_METADATA_FIELD))[0]; return Response.ok(content).header(QUERY_METADATA_FIELD, metadataHeader.getValue()).build(); @@ -417,7 +417,7 @@ public Response queryContinuous(String rsURL, QueryRequest queryRequest, String throwError(resourcesResponse, rsURL); } - String content = httpClientUtil.readObjectFromResponse(resourcesResponse); + String content = httpClientUtil.readObjectFromResponse(resourcesResponse, StandardCharsets.UTF_8); return Response.ok(content).build(); } catch (JsonProcessingException e) { throw new RuntimeException(e); diff --git a/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ResourceWebClientTest.java b/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ResourceWebClientTest.java index 6ed3c094..8b20b335 100644 --- a/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ResourceWebClientTest.java +++ b/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ResourceWebClientTest.java @@ -292,7 +292,7 @@ public void testQuery() throws JsonProcessingException { @Test public void testQueryResult() throws JsonProcessingException { String testId = "230048"; - String mockResult = "{}"; + byte[] mockResult = new byte[] {}; @@ -341,8 +341,8 @@ public void testQueryResult() throws JsonProcessingException { Response result = cut.queryResult(testURL, testId, queryRequest); assertNotNull("Result should not be null", result); // String resultContent = IOUtils.toString((InputStream) result.getEntity(), "UTF-8"); - String resultContent = (String) result.getEntity(); - assertEquals("Result should match " + mockResult, mockResult, resultContent); + byte[] resultContent = (byte[]) result.getEntity(); + assertArrayEquals("Result should match " + mockResult, mockResult, resultContent); // What if the resource has a problem? wireMockRule.stubFor(any(urlMatching("/query/.*/result")).willReturn(aResponse().withStatus(500))); diff --git a/pic-sure-util/src/main/java/edu/harvard/dbmi/avillach/util/HttpClientUtil.java b/pic-sure-util/src/main/java/edu/harvard/dbmi/avillach/util/HttpClientUtil.java index 215d0530..740eaefb 100644 --- a/pic-sure-util/src/main/java/edu/harvard/dbmi/avillach/util/HttpClientUtil.java +++ b/pic-sure-util/src/main/java/edu/harvard/dbmi/avillach/util/HttpClientUtil.java @@ -7,6 +7,7 @@ import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; @@ -19,7 +20,6 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; -import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -139,10 +139,21 @@ public List readListFromResponse(HttpResponse response, Class expected } } - public String readObjectFromResponse(HttpResponse response) { + public String readObjectFromResponse(HttpResponse response, Charset charset) { logger.debug("HttpClientUtil readObjectFromResponse(HttpResponse response)"); try { - String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + String responseBody = EntityUtils.toString(response.getEntity(), charset); + logger.debug("readObjectFromResponse() responseBody {}", responseBody); + return responseBody; + } catch (IOException e) { + throw new ApplicationException("Incorrect object type returned", e); + } + } + + public byte[] readBytesFromResponse(HttpResponse response) { + logger.debug("HttpClientUtil readObjectFromResponse(HttpResponse response)"); + try { + byte[] responseBody = EntityUtils.toByteArray(response.getEntity()); logger.debug("readObjectFromResponse() responseBody {}", responseBody); return responseBody; } catch (IOException e) {