summaryrefslogtreecommitdiffstats
path: root/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/impl/CloudEndpoint.java
diff options
context:
space:
mode:
Diffstat (limited to 'cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/impl/CloudEndpoint.java')
-rw-r--r--cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/impl/CloudEndpoint.java68
1 files changed, 68 insertions, 0 deletions
diff --git a/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/impl/CloudEndpoint.java b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/impl/CloudEndpoint.java
new file mode 100644
index 00000000000..7d1f97e55f8
--- /dev/null
+++ b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/impl/CloudEndpoint.java
@@ -0,0 +1,68 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.hosted.cd.impl;
+
+import ai.vespa.hosted.api.EndpointAuthenticator;
+import ai.vespa.hosted.cd.Endpoint;
+
+import javax.net.ssl.SSLParameters;
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static java.net.URLEncoder.encode;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A remote endpoint in a {@link CloudDeployment} of a Vespa application, reachable over HTTP.
+ *
+ * @author jonmv
+ */
+class CloudEndpoint implements Endpoint {
+
+ private final URI endpoint;
+ private final HttpClient client;
+ private final EndpointAuthenticator authenticator;
+
+ CloudEndpoint(URI endpoint, EndpointAuthenticator authenticator) {
+ this.endpoint = requireNonNull(endpoint);
+ this.authenticator = requireNonNull(authenticator);
+ SSLParameters sslParameters = new SSLParameters();
+ sslParameters.setProtocols(new String[] {"TLSv1.2" });
+ this.client = HttpClient.newBuilder()
+ .sslContext(authenticator.sslContext())
+ .connectTimeout(Duration.ofSeconds(5))
+ .version(HttpClient.Version.HTTP_1_1)
+ .sslParameters(sslParameters)
+ .build();
+ }
+
+ @Override
+ public URI uri() {
+ return endpoint;
+ }
+
+ @Override
+ public <T> HttpResponse<T> send(HttpRequest.Builder request, HttpResponse.BodyHandler<T> handler) {
+ try {
+ return client.send(authenticator.authenticated(request).build(), handler);
+ }
+ catch (IOException | InterruptedException e) {
+ throw new RuntimeException(request.build() + " failed: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public HttpRequest.Builder request(String path, Map<String, String> properties) {
+ return HttpRequest.newBuilder(endpoint.resolve(path +
+ properties.entrySet().stream()
+ .map(entry -> encode(entry.getKey(), UTF_8) + "=" + encode(entry.getValue(), UTF_8))
+ .collect(Collectors.joining("&", path.contains("?") ? "&" : "?", ""))));
+ }
+
+}