diff --git a/pom.xml b/pom.xml index c666436..ac12995 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,7 @@ 1.3.0 2.1.3 1.1.7 + 2.18.2 @@ -104,6 +105,12 @@ ${jimfs.version} test + + com.fasterxml.jackson.core + jackson-databind + ${jackson-core.version} + true + jakarta.json jakarta.json-api diff --git a/src/main/java/org/extism/sdk/chicory/HttpConfig.java b/src/main/java/org/extism/sdk/chicory/HttpConfig.java index 82b6658..fdf8dec 100644 --- a/src/main/java/org/extism/sdk/chicory/HttpConfig.java +++ b/src/main/java/org/extism/sdk/chicory/HttpConfig.java @@ -1,12 +1,16 @@ package org.extism.sdk.chicory; +import java.util.Objects; + public class HttpConfig { /** * Use {@link JdkHttpClientAdapter} for the HTTP client adapter. * Recommended on recent Java versions. */ public static HttpConfig defaultConfig() { - return new HttpConfig().withClientAdapter(new JdkHttpClientAdapter()).withJsonCodec(new JakartaJsonCodec()); + return HttpConfig.builder() + .withClientAdapter(new JdkHttpClientAdapter()) + .withJsonCodec(new JacksonJsonCodec()).build(); } /** @@ -14,19 +18,45 @@ public static HttpConfig defaultConfig() { * Recommended for Android. */ public static HttpConfig urlConnectionConfig() { - return new HttpConfig().withClientAdapter(new HttpUrlConnectionClientAdapter()).withJsonCodec(new JakartaJsonCodec()); + return HttpConfig.builder() + .withClientAdapter(new HttpUrlConnectionClientAdapter()) + .withJsonCodec(new JakartaJsonCodec()).build(); + } + + public static Builder builder() { + return new Builder(); } + public static class Builder { + HttpJsonCodec httpJsonCodec; + HttpClientAdapter httpClientAdapter; + + private Builder() {} + + public Builder withJsonCodec(HttpJsonCodec httpJsonCodec) { + this.httpJsonCodec = httpJsonCodec; + return this; + } + + public Builder withClientAdapter(HttpClientAdapter httpClientAdapter) { + this.httpClientAdapter = httpClientAdapter; + return this; + } + + public HttpConfig build() { + Objects.requireNonNull(httpJsonCodec, "httpJsonCodec is required"); + Objects.requireNonNull(httpClientAdapter, "httpClientAdapter is required"); + return new HttpConfig(httpJsonCodec, httpClientAdapter); + } + } + + HttpJsonCodec httpJsonCodec; HttpClientAdapter httpClientAdapter; - public HttpConfig withJsonCodec(HttpJsonCodec httpJsonCodec) { + public HttpConfig(HttpJsonCodec httpJsonCodec, HttpClientAdapter httpClientAdapter) { this.httpJsonCodec = httpJsonCodec; - return this; - } - - public HttpConfig withClientAdapter(HttpClientAdapter httpClientAdapter) { this.httpClientAdapter = httpClientAdapter; - return this; } + } diff --git a/src/main/java/org/extism/sdk/chicory/JacksonJsonCodec.java b/src/main/java/org/extism/sdk/chicory/JacksonJsonCodec.java new file mode 100644 index 0000000..96584dc --- /dev/null +++ b/src/main/java/org/extism/sdk/chicory/JacksonJsonCodec.java @@ -0,0 +1,70 @@ +package org.extism.sdk.chicory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JacksonJsonCodec implements HttpJsonCodec { + + ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public RequestMetadata decodeMetadata(byte[] data) { + + JsonNode request = null; + try { + request = objectMapper.readTree(data); + } catch (IOException e) { + throw new ExtismException(e); + } + + var method = request.get("method").asText(); + var uri = URI.create(request.get("url").asText()); + var headers = request.get("headers"); + + Map headersMap = new HashMap<>(); + var fields = headers.fields(); + while (fields.hasNext()) { + var entry = fields.next(); + headersMap.put(entry.getKey(), entry.getValue().asText()); + } + + return new RequestMetadata() { + @Override + public String method() { + return method; + } + + @Override + public URI uri() { + return uri; + } + + @Override + public Map headers() { + return headersMap; + } + }; + } + + public byte[] encodeHeaders(Map> headers) { + // FIXME duplicated headers are effectively overwriting duplicate values! + var objectNode = objectMapper.createObjectNode(); + for (var entry : headers.entrySet()) { + for (var v : entry.getValue()) { + objectNode.put(entry.getKey(), v); + } + } + try { + return objectMapper.writeValueAsBytes(objectNode); + } catch (JsonProcessingException e) { + throw new ExtismException(e); + } + } +} diff --git a/src/test/java/org/extism/sdk/chicory/HostEnvTest.java b/src/test/java/org/extism/sdk/chicory/HostEnvTest.java index 7999bf4..557913b 100644 --- a/src/test/java/org/extism/sdk/chicory/HostEnvTest.java +++ b/src/test/java/org/extism/sdk/chicory/HostEnvTest.java @@ -11,7 +11,7 @@ public void testShowcase() { var logger = new SystemLogger(); var config = Map.of("key", "value"); - var hostEnv = new HostEnv(new Kernel(), config, new String[0], new HttpConfig(), logger); + var hostEnv = new HostEnv(new Kernel(), config, new String[0], HttpConfig.defaultConfig(), logger); assertEquals(hostEnv.config().get("key"), "value");