From f0a500f918fc1d0ff11b3a592489fbb690374488 Mon Sep 17 00:00:00 2001 From: Luke Sikina Date: Tue, 31 Oct 2023 11:57:20 -0400 Subject: [PATCH] Proxy --- .../edu/harvard/dbmi/avillach/PicsureRS.java | 30 ++++++-- .../dbmi/avillach/service/IResourceRS.java | 23 ++++++ .../dbmi/avillach/service/ProxyWebClient.java | 70 +++++++++++++++++++ .../avillach/service/ProxyWebClientTest.java | 64 +++++++++++++++++ .../dbmi/avillach/util/HttpClientUtil.java | 2 +- 5 files changed, 184 insertions(+), 5 deletions(-) create mode 100644 pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ProxyWebClient.java create mode 100644 pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ProxyWebClientTest.java diff --git a/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java b/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java index 55e4f186..a91797ee 100644 --- a/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java +++ b/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java @@ -10,10 +10,7 @@ import javax.ws.rs.core.Response; import edu.harvard.dbmi.avillach.domain.*; -import edu.harvard.dbmi.avillach.service.FormatService; -import edu.harvard.dbmi.avillach.service.PicsureInfoService; -import edu.harvard.dbmi.avillach.service.PicsureQueryService; -import edu.harvard.dbmi.avillach.service.PicsureSearchService; +import edu.harvard.dbmi.avillach.service.*; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.info.Info; @@ -41,6 +38,9 @@ public class PicsureRS { @Inject FormatService formatService; + @Inject + ProxyWebClient proxyWebClient; + @POST @Path("/info/{resourceId}") @Operation( @@ -271,5 +271,27 @@ public QueryStatus queryMetadata(@PathParam("queryId") UUID queryId, @Context Ht public Response generateContinuousBin(QueryRequest continuousData, @Context HttpHeaders headers) { return formatService.format(continuousData, headers); } + + + @POST + @Path("/proxy/{container}/{request}") + @Operation(hidden = true) + Response postProxy( + @PathParam("container") String containerId, + @PathParam("request") String request, + String body + ) { + return proxyWebClient.postProxy(containerId, request, body); + } + + @GET + @Path("/proxy/{container}/{request}") + @Operation(hidden = true) + Response getProxy( + @PathParam("containerId") String containerId, + @PathParam("request") String request + ) { + return proxyWebClient.getProxy(containerId, request); + } } diff --git a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/IResourceRS.java b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/IResourceRS.java index bc5500a2..ad957cd4 100644 --- a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/IResourceRS.java +++ b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/IResourceRS.java @@ -6,6 +6,7 @@ import edu.harvard.dbmi.avillach.domain.*; import io.swagger.v3.oas.annotations.Operation; +import java.util.Map; import java.util.UUID; @Path("/pic-sure") @@ -81,4 +82,26 @@ default Response generateContinuousBin(QueryRequest continuousData) { throw new NotSupportedException(); } + + @POST + @Path("/proxy/{container}/{request}") + @Operation(hidden = true) + default Response postProxy( + @PathParam("containerId") String containerId, + @PathParam("request") String request, + String body + ) { + throw new NotSupportedException(); + } + + @GET + @Path("/proxy/{container}/{request}") + @Operation(hidden = true) + default Response getProxy( + @PathParam("containerId") String containerId, + @PathParam("request") String request + ) { + throw new NotSupportedException(); + } + } diff --git a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ProxyWebClient.java b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ProxyWebClient.java new file mode 100644 index 00000000..17eadafb --- /dev/null +++ b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ProxyWebClient.java @@ -0,0 +1,70 @@ +package edu.harvard.dbmi.avillach.service; + +import edu.harvard.dbmi.avillach.util.HttpClientUtil; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +public class ProxyWebClient { + private static final Logger LOG = LoggerFactory.getLogger(ProxyWebClient.class); + private final HttpClient client; + + public ProxyWebClient() { + this(HttpClientUtil.getConfiguredHttpClient()); + } + + public ProxyWebClient(HttpClient client) { + this.client = client; + } + + public Response postProxy(String containerId, String path, String body) { + try { + URI uri = new URIBuilder() + .setScheme("http") + .setHost(containerId) + .setPath(path) + .build(); + HttpPost request = new HttpPost(uri); + request.setEntity(new StringEntity(body)); + return getResponse(request); + } catch (URISyntaxException e) { + LOG.warn("Failed to construct URI. Container: {} Path: {}", containerId, path); + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public Response getProxy(String containerId, String path) { + try { + URI uri = new URIBuilder() + .setScheme("http") + .setHost(containerId) + .setPath(path) + .build(); + HttpGet request = new HttpGet(uri); + return getResponse(request); + } catch (URISyntaxException e) { + LOG.warn("Failed to construct URI. Container: {} Path: {}", containerId, path); + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Response getResponse(HttpRequestBase request) throws IOException { + HttpResponse response = client.execute(request); + return Response.ok(response.getEntity().getContent()).build(); + } +} diff --git a/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ProxyWebClientTest.java b/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ProxyWebClientTest.java new file mode 100644 index 00000000..ced606d3 --- /dev/null +++ b/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/service/ProxyWebClientTest.java @@ -0,0 +1,64 @@ +package edu.harvard.dbmi.avillach.service; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import javax.ws.rs.core.Response; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import static org.junit.Assert.*; + +@RunWith(MockitoJUnitRunner.class) +public class ProxyWebClientTest { + + @Mock + private HttpClient client; + + @Mock + private HttpResponse response; + + @Mock + private HttpEntity entity; + + @InjectMocks + private ProxyWebClient subject; + + @Test + public void shouldPostToProxy() throws IOException { + Mockito.when(client.execute(Mockito.any(HttpPost.class))) + .thenReturn(response); + Mockito.when(response.getEntity()) + .thenReturn(entity); + Mockito.when(entity.getContent()) + .thenReturn(new ByteArrayInputStream("{}".getBytes())); + + Response actual = subject.postProxy("foo", "/my/cool/path", "{}"); + + Assert.assertEquals(200, actual.getStatus()); + } + + @Test + public void shouldGetToProxy() throws IOException { + Mockito.when(client.execute(Mockito.any(HttpGet.class))) + .thenReturn(response); + Mockito.when(response.getEntity()) + .thenReturn(entity); + Mockito.when(entity.getContent()) + .thenReturn(new ByteArrayInputStream("{}".getBytes())); + + Response actual = subject.getProxy("bar", "/my/cool/path"); + + Assert.assertEquals(200, actual.getStatus()); + } +} \ No newline at end of file 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 a506b94d..79d8c52f 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 @@ -348,7 +348,7 @@ public static JsonNode simpleGetWithConfig( } } - private static HttpClient getConfiguredHttpClient() { + public static HttpClient getConfiguredHttpClient() { try { SSLConnectionSocketFactory.getSocketFactory(); SSLContext sslContext = SSLContext.getInstance("TLSv1.2");