diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 4edd932d..f3957e26 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set up JDK 17
+ - name: Set up JDK 21
uses: actions/setup-java@v3
with:
- java-version: '17'
+ java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build with Maven
diff --git a/.java-version b/.java-version
index 98d9bcb7..f2a4d8fb 100644
--- a/.java-version
+++ b/.java-version
@@ -1 +1 @@
-17
+jdk-21.0.1+12
diff --git a/pom.xml b/pom.xml
index 89036b74..15676ba7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.github.libgraviton
worker-base
jar
- 3.12.0-SNAPSHOT
+ 4.0.0-SNAPSHOT
Graviton Worker Base Library
https://github.com/libgraviton/graviton-worker-base-java
2015
@@ -131,18 +131,6 @@
guava
32.1.3-jre
-
- com.squareup.okhttp3
- okhttp
- 4.11.0
-
-
- org.jetbrains
- annotations
-
-
-
-
commons-io
commons-io
@@ -306,7 +294,7 @@
com.github.libgraviton
graviton-worker-test-base
- 3.7.0
+ 4.0.0
test
@@ -316,9 +304,9 @@
- com.github.tomakehurst
- wiremock-jre8
- 2.35.1
+ org.wiremock
+ wiremock
+ 3.3.1
test
@@ -362,10 +350,6 @@
com.google.guava
guava
-
- com.squareup.okhttp3
- okhttp
-
commons-io
commons-io
@@ -424,6 +408,12 @@
classgraph
+
+ com.github.mizosoft.methanol
+ methanol
+ 1.7.0
+
+
io.micrometer
@@ -459,8 +449,8 @@
test
- com.github.tomakehurst
- wiremock-jre8
+ org.wiremock
+ wiremock
test
@@ -511,8 +501,8 @@
maven-compiler-plugin
3.10.1
-
- 17
+
+ 21
diff --git a/src/main/java/com/github/libgraviton/workerbase/di/WorkerBaseProvider.java b/src/main/java/com/github/libgraviton/workerbase/di/WorkerBaseProvider.java
index 1de783d2..bb683542 100644
--- a/src/main/java/com/github/libgraviton/workerbase/di/WorkerBaseProvider.java
+++ b/src/main/java/com/github/libgraviton/workerbase/di/WorkerBaseProvider.java
@@ -11,24 +11,23 @@
import com.github.libgraviton.workerbase.gdk.api.endpoint.GeneratedEndpointManager;
import com.github.libgraviton.workerbase.gdk.api.endpoint.exception.UnableToLoadEndpointAssociationsException;
import com.github.libgraviton.workerbase.gdk.api.gateway.GravitonGateway;
-import com.github.libgraviton.workerbase.gdk.api.gateway.OkHttpGateway;
-import com.github.libgraviton.workerbase.gdk.api.gateway.okhttp.OkHttpGatewayFactory;
+import com.github.libgraviton.workerbase.gdk.api.gateway.MethanolGateway;
+import com.github.libgraviton.workerbase.gdk.api.gateway.http.MethanolGatewayFactory;
import com.github.libgraviton.workerbase.gdk.requestexecutor.auth.Authenticator;
import com.github.libgraviton.workerbase.gdk.requestexecutor.auth.GravitonGatewayAuthenticator;
import com.github.libgraviton.workerbase.gdk.serialization.mapper.RqlObjectMapper;
import com.github.libgraviton.workerbase.helper.EventStatusHandler;
import com.github.libgraviton.workerbase.helper.WorkerProperties;
+import com.github.mizosoft.methanol.Methanol;
import io.activej.inject.Key;
import io.activej.inject.annotation.Provides;
import io.activej.inject.annotation.Transient;
import io.activej.inject.binding.Binding;
import io.activej.inject.module.AbstractModule;
-import okhttp3.OkHttpClient;
-import okhttp3.Protocol;
import java.io.IOException;
+import java.net.http.HttpClient;
import java.text.SimpleDateFormat;
-import java.util.Collections;
import java.util.Properties;
import java.util.TimeZone;
import java.util.concurrent.*;
@@ -42,7 +41,7 @@ protected void configure() {
*/
generate(GravitonGateway.class, (bindings, scope, key) -> {
if (key.getType().equals(GravitonGateway.class)) {
- return Binding.to(Key.of(OkHttpGateway.class));
+ return Binding.to(Key.of(MethanolGateway.class));
}
return null;
});
@@ -77,25 +76,16 @@ public static GravitonApi gravitonApi(EndpointManager endpointManager, ObjectMap
}
@Provides
- public static OkHttpClient getOkHttpClient() throws Exception {
+ public static Methanol getMethanol() throws Exception {
final boolean hasRetry = WorkerProperties.HTTP_CLIENT_DORETRY.get().equals("true");
- final boolean forceHttp11 = WorkerProperties.HTTP_CLIENT_FORCE_HTTP1_1.get().equals("true");
final boolean trustAll = WorkerProperties.HTTP_CLIENT_TLS_TRUST_ALL.get().equals("true");
- OkHttpClient client = OkHttpGatewayFactory.getInstance(hasRetry);
- if (trustAll) {
- client = OkHttpGatewayFactory.getAllTrustingInstance(hasRetry, client);
- }
-
- if (forceHttp11) {
- client = client
- .newBuilder()
- .retryOnConnectionFailure(true)
- .protocols(Collections.singletonList(Protocol.HTTP_1_1))
- .build();
- }
+ return MethanolGatewayFactory.getInstance(hasRetry, trustAll);
+ }
- return client;
+ @Provides
+ public static HttpClient getHttpClient() throws Exception {
+ return getMethanol();
}
@Provides
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/api/NoopResponse.java b/src/main/java/com/github/libgraviton/workerbase/gdk/api/NoopResponse.java
index e2c25174..5a100f0c 100644
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/api/NoopResponse.java
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/api/NoopResponse.java
@@ -15,7 +15,6 @@ public NoopResponse(NoopRequest request) {
this.request = request;
this.code = -1;
this.isSuccessful = true;
- this.message = "This is not the response you are looking for";
this.body = null;
this.headers = new HeaderBag.Builder().build();
}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/api/Response.java b/src/main/java/com/github/libgraviton/workerbase/gdk/api/Response.java
index b3c13762..147a57fe 100644
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/api/Response.java
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/api/Response.java
@@ -26,8 +26,6 @@ public class Response {
protected int code;
- protected String message;
-
protected HeaderBag headers;
protected byte[] body;
@@ -43,7 +41,6 @@ protected Response(com.github.libgraviton.workerbase.gdk.api.Response.Builder bu
request = builder.request;
code = builder.code;
isSuccessful = builder.isSuccessful;
- message = builder.message;
body = builder.body;
headers = builder.headerBuilder.build();
}
@@ -151,16 +148,10 @@ public int getCode() {
return code;
}
- public String getMessage() {
- return message;
- }
-
public static class Builder {
protected int code;
- protected String message;
-
protected final Request request;
protected byte[] body;
@@ -184,11 +175,6 @@ public Builder successful(boolean isSuccessful) {
return this;
}
- public Builder message(String message) {
- this.message = message;
- return this;
- }
-
public Builder body(byte[] body) {
this.body = body;
return this;
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/MethanolGateway.java b/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/MethanolGateway.java
new file mode 100644
index 00000000..fd711d8a
--- /dev/null
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/MethanolGateway.java
@@ -0,0 +1,124 @@
+package com.github.libgraviton.workerbase.gdk.api.gateway;
+
+import com.github.libgraviton.workerbase.annotation.GravitonWorkerDiScan;
+import com.github.libgraviton.workerbase.gdk.api.Request;
+import com.github.libgraviton.workerbase.gdk.api.Response;
+import com.github.libgraviton.workerbase.gdk.api.header.Header;
+import com.github.libgraviton.workerbase.gdk.api.header.HeaderBag;
+import com.github.libgraviton.workerbase.gdk.api.multipart.FilePart;
+import com.github.libgraviton.workerbase.gdk.api.multipart.Part;
+import com.github.libgraviton.workerbase.gdk.exception.CommunicationException;
+import com.github.mizosoft.methanol.Methanol;
+import com.github.mizosoft.methanol.MultipartBodyPublisher;
+import com.github.mizosoft.methanol.MutableRequest;
+import io.activej.inject.annotation.Inject;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.Map;
+
+@GravitonWorkerDiScan
+public class MethanolGateway implements GravitonGateway {
+
+ @Inject
+ Methanol httpClient;
+
+ @Inject
+ public MethanolGateway() {
+
+ }
+
+ public HttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ public Response execute(Request request) throws CommunicationException {
+ try {
+ HttpRequest req = generateRequest(request);
+
+ HttpResponse response = httpClient.send(req, HttpResponse.BodyHandlers.ofByteArray());
+ return generateResponse(request, response);
+ } catch (FileNotFoundException | URISyntaxException e) {
+ throw new CommunicationException("Unable to create request", e);
+ } catch (IOException | InterruptedException e) {
+ throw new CommunicationException("Error sending request", e);
+ }
+ }
+
+ private HttpRequest generateRequest(Request request) throws FileNotFoundException, URISyntaxException {
+ HttpRequest.BodyPublisher body;
+
+ if (request.isMultipartRequest()) {
+ body = generateMultipartRequestBody(request);
+ } else {
+ if (null == request.getBodyBytes()) {
+ body = HttpRequest.BodyPublishers.noBody();
+ } else {
+ body = HttpRequest.BodyPublishers.ofByteArray(request.getBodyBytes());
+ }
+ }
+
+ HttpRequest.Builder builder = MutableRequest.newBuilder()
+ .uri(request.getUrl().toURI())
+ .method(request.getMethod().asString(), body);
+
+ // set headers
+ for (Map.Entry header : request.getHeaders().all().entrySet()) {
+ for (String value : header.getValue()) {
+ builder.header(header.getKey(), value);
+ }
+ }
+
+ return builder.build();
+ }
+
+ private MultipartBodyPublisher generateMultipartRequestBody(Request request) throws FileNotFoundException {
+ MultipartBodyPublisher.Builder multipartBuilder = MultipartBodyPublisher.newBuilder();
+
+ int partNumber = 1;
+ for (Part part : request.getParts()) {
+ if (part.getFormName() != null) {
+ multipartBuilder.formPart(part.getFormName(), HttpRequest.BodyPublishers.ofByteArray(part.getBody()));
+ } else {
+ String partName = String.format("part-%s", partNumber);
+ multipartBuilder.formPart(partName, HttpRequest.BodyPublishers.ofByteArray(part.getBody()));
+ }
+ partNumber++;
+ }
+
+ for (FilePart part : request.getFileParts()) {
+ if (part.getFormName() != null) {
+ multipartBuilder.filePart(part.getFormName(), part.getBody().toPath());
+ } else {
+ String partName = String.format("part-%s", partNumber);
+ multipartBuilder.filePart(partName, part.getBody().toPath(), com.github.mizosoft.methanol.MediaType.parse(part.getContentType()));
+ }
+ partNumber++;
+ }
+
+ return multipartBuilder.build();
+ }
+
+ private Response generateResponse(Request req, HttpResponse resp) {
+ Response.Builder responseBuilder = new Response.Builder(req);
+
+ return responseBuilder
+ .code(resp.statusCode())
+ .headers(createResponseHeaders(resp.headers()))
+ .successful(resp.statusCode() < 300)
+ .body(resp.body())
+ .build();
+ }
+
+ private HeaderBag.Builder createResponseHeaders(HttpHeaders headers) {
+ HeaderBag.Builder builder = new HeaderBag.Builder();
+ headers.map().forEach(builder::set);
+ return builder;
+ }
+
+}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/OkHttpGateway.java b/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/OkHttpGateway.java
deleted file mode 100644
index 41248cf3..00000000
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/OkHttpGateway.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package com.github.libgraviton.workerbase.gdk.api.gateway;
-
-import com.github.libgraviton.workerbase.annotation.GravitonWorkerDiScan;
-import com.github.libgraviton.workerbase.gdk.api.Request;
-import com.github.libgraviton.workerbase.gdk.api.Response;
-import com.github.libgraviton.workerbase.gdk.api.header.Header;
-import com.github.libgraviton.workerbase.gdk.api.header.HeaderBag;
-import com.github.libgraviton.workerbase.gdk.api.multipart.FilePart;
-import com.github.libgraviton.workerbase.gdk.api.multipart.Part;
-import com.github.libgraviton.workerbase.gdk.exception.CommunicationException;
-import com.github.libgraviton.workerbase.gdk.exception.UnsuccessfulRequestException;
-import io.activej.inject.annotation.Inject;
-import okhttp3.*;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-@GravitonWorkerDiScan
-public class OkHttpGateway implements GravitonGateway {
-
- @Inject
- OkHttpClient okHttp;
-
- @Inject
- public OkHttpGateway() {
-
- }
-
- public OkHttpClient getOkHttp() {
- return okHttp;
- }
-
- public Response execute(Request request) throws CommunicationException {
- okhttp3.Request okHttpRequest = generateRequest(request);
-
- try (okhttp3.Response okHttpResponse = okHttp.newCall(okHttpRequest).execute()) {
- byte[] body = okHttpResponse.body().bytes();
- return generateResponse(request, okHttpResponse, body);
- } catch (IOException e) {
- throw new UnsuccessfulRequestException(
- String.format("'%s' to '%s' failed.", request.getMethod(), request.getUrl()),
- e
- );
- }
- }
-
- private okhttp3.Request generateRequest(Request request) {
- RequestBody okHttpBody;
- if (request.isMultipartRequest()) {
- okHttpBody = generateMultipartRequestBody(request);
- } else {
- okHttpBody = generateDefaultRequestBody(request);
- }
-
- okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
- return requestBuilder
- .method(request.getMethod().asString(), okHttpBody)
- .url(request.getUrl())
- .headers(createRequestHeaders(request.getHeaders()))
- .build();
- }
-
- private RequestBody generateMultipartRequestBody(Request request) {
- MultipartBody.Builder builder = new MultipartBody.Builder();
- // string based parts
- for (Part part : request.getParts()) {
- MultipartBody.Part bodyPart;
- RequestBody requestBody = RequestBody.create(part.getBody());
- if (part.getFormName() != null) {
- bodyPart = MultipartBody.Part.createFormData(part.getFormName(), null, requestBody);
- } else {
- bodyPart = MultipartBody.Part.create(null, requestBody);
- }
-
- builder.addPart(bodyPart);
- }
- // file parts
- for (FilePart part : request.getFileParts()) {
- MultipartBody.Part bodyPart;
- RequestBody requestBody = RequestBody.create(part.getBody(), MediaType.parse(part.getContentType()));
- if (part.getFormName() != null) {
- bodyPart = MultipartBody.Part.createFormData(part.getFormName(), null, requestBody);
- } else {
- bodyPart = MultipartBody.Part.create(null, requestBody);
- }
-
- builder.addPart(bodyPart);
- }
-
- return builder.build();
- }
-
- private RequestBody generateDefaultRequestBody(Request request) {
- if (null == request.getBodyBytes()) {
- return null;
- }
-
- return RequestBody.create(
- request.getBodyBytes(),
- MediaType.parse(
- String.format(
- "%s; charset=utf-8",
- request.getHeaders().get("Content-Type").toString()
- )
- )
- );
- }
-
- private Response generateResponse(Request request, okhttp3.Response okHttpResponse, byte[] body) {
- Response.Builder responseBuilder = new Response.Builder(request);
- return responseBuilder
- .code(okHttpResponse.code())
- .headers(createResponseHeaders(okHttpResponse.headers()))
- .message(okHttpResponse.message())
- .successful(okHttpResponse.isSuccessful())
- .body(body)
- .build();
- }
-
- private Headers createRequestHeaders(HeaderBag headerBag) {
- Headers.Builder builder = new Headers.Builder();
- for (Map.Entry header : headerBag.all().entrySet()) {
- for (String value : header.getValue()) {
- builder.add(header.getKey(), value);
- }
- }
- return builder.build();
- }
-
- private HeaderBag.Builder createResponseHeaders(Headers okhttpHeaders) {
- HeaderBag.Builder builder = new HeaderBag.Builder();
- for (Map.Entry> header : okhttpHeaders.toMultimap().entrySet()) {
- builder.set(header.getKey(), header.getValue());
- }
- return builder;
- }
-
-}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/http/MethanolGatewayFactory.java b/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/http/MethanolGatewayFactory.java
new file mode 100644
index 00000000..3a9e647e
--- /dev/null
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/http/MethanolGatewayFactory.java
@@ -0,0 +1,76 @@
+package com.github.libgraviton.workerbase.gdk.api.gateway.http;
+
+import com.github.libgraviton.workerbase.gdk.util.http.interceptor.RetryInterceptor;
+import com.github.mizosoft.methanol.Methanol;
+
+import javax.net.ssl.*;
+import java.net.Socket;
+import java.net.http.HttpClient;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+public class MethanolGatewayFactory {
+
+ private static final TrustManager MOCK_TRUST_MANAGER = new X509ExtendedTrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) throws CertificateException {
+
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) throws CertificateException {
+
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {
+
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {
+
+ }
+
+ @Override
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return new java.security.cert.X509Certificate[0];
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+
+ }
+
+ @Override
+ public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
+ // empty method
+ }
+ };
+
+ /**
+ * gets the normal instance without retry interceptor
+ *
+ * @return instance
+ */
+ public static Methanol getInstance(boolean hasRetry, boolean trustAll) throws NoSuchAlgorithmException, KeyManagementException {
+ Methanol.Builder builder = Methanol.newBuilder();
+ if (trustAll) {
+ SSLContext sslContext = SSLContext.getInstance("SSL"); // OR TLS
+ sslContext.init(null, new TrustManager[]{MOCK_TRUST_MANAGER}, new SecureRandom());
+
+ builder.sslContext(sslContext);
+ }
+
+ if (hasRetry) {
+ builder.interceptor(new RetryInterceptor());
+ }
+
+ builder.followRedirects(HttpClient.Redirect.ALWAYS);
+
+ return builder.build();
+ }
+}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/okhttp/OkHttpGatewayFactory.java b/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/okhttp/OkHttpGatewayFactory.java
deleted file mode 100644
index 4fe03930..00000000
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/api/gateway/okhttp/OkHttpGatewayFactory.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.github.libgraviton.workerbase.gdk.api.gateway.okhttp;
-
-import com.github.libgraviton.workerbase.gdk.util.okhttp.interceptor.RetryInterceptor;
-import com.github.libgraviton.workerbase.helper.WorkerUtil;
-import okhttp3.OkHttpClient;
-import okhttp3.OkHttpClient.Builder;
-
-import javax.net.ssl.X509TrustManager;
-import java.util.concurrent.TimeUnit;
-
-public class OkHttpGatewayFactory {
-
- /**
- * gets the normal instance without retry interceptor
- *
- * @return instance
- */
- public static OkHttpClient getInstance(boolean hasRetry) {
- return getBaseBuilder(hasRetry).build();
- }
-
- /**
- * returns a client that trusts all certs
- *
- * @param hasRetry if should have retry or not
- * @return
- * @throws Exception
- */
- public static OkHttpClient getAllTrustingInstance(boolean hasRetry, OkHttpClient baseClient) throws Exception {
- Builder baseBuilder;
- if (baseClient != null) {
- baseBuilder = baseClient.newBuilder();
- } else {
- baseBuilder = getBaseBuilder(hasRetry);
- }
-
- baseBuilder
- .sslSocketFactory(WorkerUtil.getAllTrustingSocketFactory(), (X509TrustManager) WorkerUtil.getAllTrustingTrustManagers()[0])
- .hostnameVerifier((hostname, session) -> true);
-
- return baseBuilder.build();
- }
-
- private static Builder getBaseBuilder(boolean hasRetry) {
- Builder builder = new Builder()
- .connectTimeout(60, TimeUnit.SECONDS)
- .writeTimeout(60, TimeUnit.SECONDS)
- .readTimeout(60, TimeUnit.SECONDS);
-
- if (hasRetry) {
- builder.addInterceptor(new RetryInterceptor());
- }
-
- return builder;
- }
-}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/auth/BasicAuth.java b/src/main/java/com/github/libgraviton/workerbase/gdk/auth/BasicAuth.java
index 975bd342..e9d97b3d 100644
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/auth/BasicAuth.java
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/auth/BasicAuth.java
@@ -1,13 +1,12 @@
package com.github.libgraviton.workerbase.gdk.auth;
import com.github.libgraviton.workerbase.gdk.api.header.HeaderBag;
-import com.github.libgraviton.workerbase.gdk.auth.HeaderAuth;
-import okio.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
public class BasicAuth implements HeaderAuth {
@@ -35,7 +34,8 @@ public String basic() {
public String basic(Charset charset) {
String usernameAndPassword = username + ":" + password;
byte[] bytes = usernameAndPassword.getBytes(charset);
- String encoded = ByteString.of(bytes).base64();
- return "Basic ".concat(encoded);
+
+ String encodedString = Base64.getEncoder().encodeToString(bytes);
+ return "Basic ".concat(encodedString);
}
}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/exception/UnsuccessfulResponseException.java b/src/main/java/com/github/libgraviton/workerbase/gdk/exception/UnsuccessfulResponseException.java
index 03afe024..6673a9f0 100644
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/exception/UnsuccessfulResponseException.java
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/exception/UnsuccessfulResponseException.java
@@ -1,7 +1,6 @@
package com.github.libgraviton.workerbase.gdk.exception;
import com.github.libgraviton.workerbase.gdk.api.Response;
-import com.github.libgraviton.workerbase.gdk.exception.CommunicationException;
/**
* Whenever a received response code is not within 200 - 299.
@@ -21,11 +20,10 @@ public Response getResponse() {
private static String generateMessage(Response response) {
return String.format(
- "Failed '%s' to '%s'. Response was '%d' - '%s' with body '%s'.",
+ "Failed '%s' to '%s'. Response was '%d' - body '%s'.",
response.getRequest().getMethod(),
response.getRequest().getUrl(),
response.getCode(),
- response.getMessage(),
response.getBody()
);
}
diff --git a/src/main/java/com/github/libgraviton/workerbase/gdk/util/okhttp/interceptor/RetryInterceptor.java b/src/main/java/com/github/libgraviton/workerbase/gdk/util/http/interceptor/RetryInterceptor.java
similarity index 59%
rename from src/main/java/com/github/libgraviton/workerbase/gdk/util/okhttp/interceptor/RetryInterceptor.java
rename to src/main/java/com/github/libgraviton/workerbase/gdk/util/http/interceptor/RetryInterceptor.java
index 8a3dd7e5..363d22e5 100644
--- a/src/main/java/com/github/libgraviton/workerbase/gdk/util/okhttp/interceptor/RetryInterceptor.java
+++ b/src/main/java/com/github/libgraviton/workerbase/gdk/util/http/interceptor/RetryInterceptor.java
@@ -1,19 +1,19 @@
-package com.github.libgraviton.workerbase.gdk.util.okhttp.interceptor;
+package com.github.libgraviton.workerbase.gdk.util.http.interceptor;
import com.github.libgraviton.workerbase.util.RetryRegistry;
+import com.github.mizosoft.methanol.Methanol;
import io.github.resilience4j.core.functions.CheckedSupplier;
-import okhttp3.Interceptor;
-import okhttp3.Request;
-import okhttp3.Response;
-import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
-public class RetryInterceptor implements Interceptor {
+public class RetryInterceptor implements Methanol.Interceptor {
private static final Logger LOG = LoggerFactory.getLogger(RetryInterceptor.class);
private final int retryCount;
@@ -22,7 +22,7 @@ public class RetryInterceptor implements Interceptor {
public RetryInterceptor() {
this(
6 * 10, // 10 minutes
- 10
+ 5
);
}
@@ -31,15 +31,13 @@ public RetryInterceptor(int retryCount, int waitInBetween) {
this.waitInBetween = waitInBetween;
}
- @Override public @NotNull Response intercept(@NotNull Chain chain) throws IOException {
+ @Override
+ public HttpResponse intercept(HttpRequest request, Chain chain) throws IOException {
+ CheckedSupplier> responseSupplier = () -> {
+ HttpResponse response = chain.forward(request);
- final Request request = chain.request();
- CheckedSupplier responseSupplier = () -> {
- Response response = chain.proceed(request);
-
- if (List.of(500, 502, 503).contains(response.code())) {
- response.close();
- throw new IOException("Got response status " + response.code());
+ if (List.of(500, 502, 503).contains(response.statusCode())) {
+ throw new IOException("Got response status " + response.statusCode());
}
return response;
@@ -61,4 +59,9 @@ public RetryInterceptor(int retryCount, int waitInBetween) {
}
}
+ @Override
+ public CompletableFuture> interceptAsync(HttpRequest request, Chain chain) {
+ LOG.warn("Called async for retryInterceptor; is not supported.");
+ return chain.forwardAsync(request);
+ }
}
diff --git a/src/main/java/com/github/libgraviton/workerbase/helper/WorkerScope.java b/src/main/java/com/github/libgraviton/workerbase/helper/WorkerScope.java
index bc3998d3..939d9b04 100644
--- a/src/main/java/com/github/libgraviton/workerbase/helper/WorkerScope.java
+++ b/src/main/java/com/github/libgraviton/workerbase/helper/WorkerScope.java
@@ -7,9 +7,9 @@
import com.github.libgraviton.workerbase.gdk.GravitonApi;
import com.github.libgraviton.workerbase.gdk.GravitonFileEndpoint;
import io.activej.inject.annotation.Inject;
-import okhttp3.HttpUrl;
import org.apache.commons.collections4.map.HashedMap;
+import java.net.URI;
import java.util.Map;
import java.util.Properties;
@@ -65,17 +65,24 @@ public Map getScopeCacheMap() {
* @return corrected url
*/
public String convertToGravitonUrl(String url) {
- HttpUrl baseUrl = HttpUrl.parse(WorkerProperties.GRAVITON_BASE_URL.get());
+ try {
+ URI baseUri = new URI(WorkerProperties.GRAVITON_BASE_URL.get());
+ URI srcUri = new URI(url);
- // convert
- HttpUrl targetUrl = HttpUrl
- .parse(url)
- .newBuilder()
- .host(baseUrl.host())
- .port(baseUrl.port())
- .scheme(baseUrl.scheme())
- .build();
+ URI newUri = new URI(
+ baseUri.getScheme(),
+ baseUri.getUserInfo(),
+ baseUri.getHost(),
+ baseUri.getPort(),
+ srcUri.getPath(),
+ srcUri.getQuery(),
+ srcUri.getFragment()
+ );
- return targetUrl.toString();
+ return newUri.toURL().toString();
+ } catch (Throwable t) {
+ }
+
+ return url;
}
}
diff --git a/src/main/java/com/github/libgraviton/workerbase/util/DownloadClient.java b/src/main/java/com/github/libgraviton/workerbase/util/DownloadClient.java
index 64987b2a..449afec0 100644
--- a/src/main/java/com/github/libgraviton/workerbase/util/DownloadClient.java
+++ b/src/main/java/com/github/libgraviton/workerbase/util/DownloadClient.java
@@ -1,16 +1,22 @@
package com.github.libgraviton.workerbase.util;
-import java.io.File;
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.nio.file.Files;
+import java.nio.file.Path;
import java.util.Map;
import com.github.libgraviton.workerbase.helper.DependencyInjection;
-import okhttp3.*;
-import okio.BufferedSink;
-import okio.Okio;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class DownloadClient {
+ private static final Logger LOG = LoggerFactory.getLogger(DownloadClient.class);
+
/**
* Downloads a file to disk
*
@@ -19,15 +25,20 @@ public class DownloadClient {
* @throws Exception
*/
public static void downloadFile(String url, final String targetPath, Map requestHeaders) {
- try (ResponseBody body = getResponseBody(url, requestHeaders)) {
- File file = new File(targetPath);
- BufferedSink sink = Okio.buffer(Okio.sink(file));
-
- sink.writeAll(body.source());
- sink.flush();
- sink.close();
- } catch (Exception e) {
- throw new RuntimeException("Error downloading URL '" + url + "'", e);
+ try {
+ HttpClient httpClient = DependencyInjection.getInstance(HttpClient.class);
+
+ HttpRequest.Builder reqBuilder = HttpRequest.newBuilder(new URI(url));
+ requestHeaders.forEach(reqBuilder::header);
+
+ httpClient.send(
+ reqBuilder.build(),
+ HttpResponse.BodyHandlers.ofFile(Path.of(targetPath))
+ );
+
+ LOG.info("Downloaded '{}' to path '{}'", url, targetPath);
+ } catch (Throwable t) {
+ LOG.error("Error downloading url '{}'", url, t);
}
}
@@ -37,22 +48,23 @@ public static void downloadFile(String url, final String targetPath) {
@Deprecated(since = "Use writeFileContentToDisk(), File and streams to deal with files, not byte arrays!")
public static byte[] downloadFileBytes(String url) throws IOException {
- try (ResponseBody body = getResponseBody(url, Map.of())) {
- return body.bytes();
- }
- }
-
- private static ResponseBody getResponseBody(String url, Map requestHeaders) throws IOException {
- Request request = new Request.Builder().url(url).headers(Headers.of(requestHeaders)).build();
+ java.io.File finalTemp = java.io.File.createTempFile("grv-file", ".tmp");
- OkHttpClient client = DependencyInjection.getInstance(OkHttpClient.class);
- Response response = client.newCall(request).execute();
+ // download
+ downloadFile(url, finalTemp.getAbsolutePath(), Map.of());
- if (response.code() < 200 || response.code() > 300) {
- throw new RuntimeException(
- "Download of url '" + url + "' returned an unexpected status code of " + response.code());
+ if (!finalTemp.exists()) {
+ LOG.error("URL '{}' could not be downloaded", url);
+ throw new IOException("Could not download URL");
}
- return response.body();
+ byte[] contents = Files.readAllBytes(finalTemp.toPath());
+
+ // delete file
+ finalTemp.delete();
+
+ // read into array
+ return contents;
}
+
}
diff --git a/src/test/java/com/github/libgraviton/workerbase/gdk/api/ResponseTest.java b/src/test/java/com/github/libgraviton/workerbase/gdk/api/ResponseTest.java
index 29a92b4d..9feef362 100644
--- a/src/test/java/com/github/libgraviton/workerbase/gdk/api/ResponseTest.java
+++ b/src/test/java/com/github/libgraviton/workerbase/gdk/api/ResponseTest.java
@@ -25,7 +25,6 @@ public void setup() throws Exception {
response = new Response.Builder(request)
.body("{\"code\":0}".getBytes())
.successful(true)
- .message("a message")
.code(200)
.build();
response.setObjectMapper(new ObjectMapper());
@@ -59,7 +58,6 @@ public void testSuccessfulDeserializeBody() throws DeserializationException {
response.getBodyItem(SerializationTestClass.class);
Assertions.assertTrue(response.isSuccessful());
Assertions.assertEquals(200, response.getCode());
- Assertions.assertEquals("a message", response.getMessage());
Assertions.assertEquals("{\"code\":0}", response.getBody());
Assertions.assertEquals(request, response.getRequest());
Assertions.assertEquals(0, response.getHeaders().all().size());
@@ -76,7 +74,6 @@ public void testDeserializeBodyAsList() throws Exception {
response = new Response.Builder(request)
.body(new ObjectMapper().writeValueAsString(testClasses).getBytes())
.successful(true)
- .message("a message")
.code(200)
.build();
response.setObjectMapper(new ObjectMapper());
diff --git a/src/test/java/com/github/libgraviton/workerbase/gdk/okhttp/RetryInterceptorTest.java b/src/test/java/com/github/libgraviton/workerbase/gdk/okhttp/RetryInterceptorTest.java
index 3867cb8d..eb5efd8b 100644
--- a/src/test/java/com/github/libgraviton/workerbase/gdk/okhttp/RetryInterceptorTest.java
+++ b/src/test/java/com/github/libgraviton/workerbase/gdk/okhttp/RetryInterceptorTest.java
@@ -1,17 +1,20 @@
package com.github.libgraviton.workerbase.gdk.okhttp;
-import com.github.libgraviton.workerbase.gdk.util.okhttp.interceptor.RetryInterceptor;
+import com.github.libgraviton.workerbase.gdk.util.http.interceptor.RetryInterceptor;
import com.github.libgraviton.workertestbase.WorkerTestExtension;
+import com.github.mizosoft.methanol.Methanol;
+import com.github.mizosoft.methanol.MutableRequest;
import com.github.tomakehurst.wiremock.stubbing.Scenario;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import java.io.IOException;
import java.net.ConnectException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
@@ -21,22 +24,21 @@ public class RetryInterceptorTest {
public static WorkerTestExtension workerTestExtension = (new WorkerTestExtension())
.setStartWiremock(true);
- private OkHttpClient client;
+ private HttpClient client;
@Test
public void testWrongHostHandling() {
Assertions.assertThrows(IOException.class, () -> {
RetryInterceptor retryInterceptor = new RetryInterceptor(5, 1);
- client = new OkHttpClient.Builder()
- .addInterceptor(retryInterceptor)
+ client = Methanol.newBuilder()
+ .interceptor(retryInterceptor)
.build();
- Request request = new Request.Builder()
- .url("http://myservice/my-precious-url/4")
- .build();
+ HttpRequest request = MutableRequest.newBuilder(new URI("http://myservice/my-precious-url/4"))
+ .build();
- client.newCall(request).execute();
+ client.send(request, HttpResponse.BodyHandlers.discarding());
});
}
@@ -45,16 +47,15 @@ public void testWrongPortHandling() throws Exception {
Assertions.assertThrows(IOException.class, () -> {
RetryInterceptor retryInterceptor = new RetryInterceptor(5, 1);
- client = new OkHttpClient.Builder()
- .addInterceptor(retryInterceptor)
- .build();
+ client = Methanol.newBuilder()
+ .interceptor(retryInterceptor)
+ .build();
- Request request = new Request.Builder()
- .url("http://localhost:9988")
- .build();
+ HttpRequest request = MutableRequest.newBuilder(new URI("http://localhost:9988"))
+ .build();
try {
- client.newCall(request).execute();
+ client.send(request, HttpResponse.BodyHandlers.discarding());
} catch (ConnectException e) {
throw e;
}
@@ -91,18 +92,17 @@ public void testWrongHttpStatusHandling() throws Exception {
RetryInterceptor retryInterceptor = new RetryInterceptor(5, 1);
- client = new OkHttpClient.Builder()
- .addInterceptor(retryInterceptor)
- .build();
+ client = Methanol.newBuilder()
+ .interceptor(retryInterceptor)
+ .build();
- Request request = new Request.Builder()
- .url(workerTestExtension.getWiremockUrl() + "/service")
- .build();
+ HttpRequest request = MutableRequest.newBuilder(new URI(workerTestExtension.getWiremockUrl() + "/service"))
+ .build();
- Response response = client.newCall(request).execute();
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
- Assertions.assertEquals(200, response.code());
- Assertions.assertEquals("YEEEEES!", response.body().string());
+ Assertions.assertEquals(200, response.statusCode());
+ Assertions.assertEquals("YEEEEES!", response.body());
}
}
diff --git a/src/test/java/com/github/libgraviton/workerbase/util/DownloadClientTest.java b/src/test/java/com/github/libgraviton/workerbase/util/DownloadClientTest.java
new file mode 100644
index 00000000..6734534e
--- /dev/null
+++ b/src/test/java/com/github/libgraviton/workerbase/util/DownloadClientTest.java
@@ -0,0 +1,50 @@
+package com.github.libgraviton.workerbase.util;
+
+import com.github.libgraviton.workertestbase.WorkerTestExtension;
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import java.io.File;
+import java.util.Map;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+
+public class DownloadClientTest {
+
+ @RegisterExtension
+ public static WorkerTestExtension workerTestExtension = (new WorkerTestExtension())
+ .setStartWiremock(true);
+
+ @Test
+ public void testBasicDownload() {
+ String target = "/tmp/PDF-TEST-FILE.pdf";
+ String url = workerTestExtension.getWiremockUrl() + "/test.pdf";
+
+ StubMapping redir = workerTestExtension.getWireMockServer()
+ .stubFor(
+ get(urlMatching("/test.pdf"))
+ .withHeader("FRANZ", equalTo("TEST"))
+ .willReturn(
+ aResponse().withStatus(301).withHeader("location", "/file/test.pdf")
+ )
+ );
+
+ StubMapping filestub = workerTestExtension.getWireMockServer()
+ .stubFor(
+ get(urlMatching("/file/test.pdf"))
+ // the transient headers
+ .willReturn(
+ aResponse().withBodyFile("test.pdf").withStatus(200)
+ )
+ );
+
+ DownloadClient.downloadFile(url, target, Map.of("FRANZ", "TEST"));
+
+ File file = new File(target);
+ Assertions.assertEquals(7021, file.length());
+ file.delete();
+ }
+
+}
diff --git a/src/test/resources/files/test.pdf b/src/test/resources/__files/test.pdf
similarity index 100%
rename from src/test/resources/files/test.pdf
rename to src/test/resources/__files/test.pdf