Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import java.util.List;

/**
* Holds constants for the well-known properties defined by the Proxy-Wasm ABI.
*
* see: <a href="https://github.com/proxy-wasm/spec/tree/main/abi-versions/v0.1.0#well-known-properties">spec</a>
*/
public final class WellKnownProperties {
private WellKnownProperties() {}

Expand Down
25 changes: 18 additions & 7 deletions proxy-wasm-jaxrs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,30 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>io.roastedroot</groupId>
<artifactId>proxy-wasm-java-host</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<optional>true</optional>
</dependency>

<!-- Depend on a minimal set of jakarta/jaxrs apis -->
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
Expand All @@ -42,20 +60,13 @@
<artifactId>jakarta.inject-api</artifactId>
<scope>provided</scope>
</dependency>

<!-- Depend on a minimal set of jakarta/jaxrs apis -->
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>

<!-- Let's test with Quarkus -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
package io.roastedroot.proxywasm.jaxrs;

import static io.roastedroot.proxywasm.Helpers.bytes;
import static io.roastedroot.proxywasm.Helpers.string;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_DNS_SAN_LOCAL_CERTIFICATE;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_DNS_SAN_PEER_CERTIFICATE;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_ID;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_MTLS;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_REQUESTED_SERVER_NAME;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_SHA256_PEER_CERTIFICATE_DIGEST;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_SUBJECT_LOCAL_CERTIFICATE;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_SUBJECT_PEER_CERTIFICATE;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_TLS_VERSION;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_URI_SAN_LOCAL_CERTIFICATE;
import static io.roastedroot.proxywasm.WellKnownProperties.CONNECTION_URI_SAN_PEER_CERTIFICATE;
import static io.roastedroot.proxywasm.WellKnownProperties.DESTINATION_ADDRESS;
import static io.roastedroot.proxywasm.WellKnownProperties.DESTINATION_PORT;
import static io.roastedroot.proxywasm.WellKnownProperties.REQUEST_DURATION;
import static io.roastedroot.proxywasm.WellKnownProperties.REQUEST_PROTOCOL;
import static io.roastedroot.proxywasm.WellKnownProperties.REQUEST_SIZE;
import static io.roastedroot.proxywasm.WellKnownProperties.REQUEST_TIME;
import static io.roastedroot.proxywasm.WellKnownProperties.REQUEST_TOTAL_SIZE;
import static io.roastedroot.proxywasm.WellKnownProperties.RESPONSE_SIZE;
import static io.roastedroot.proxywasm.WellKnownProperties.RESPONSE_TOTAL_SIZE;
import static io.roastedroot.proxywasm.WellKnownProperties.SOURCE_ADDRESS;
import static io.roastedroot.proxywasm.WellKnownProperties.SOURCE_PORT;

import io.roastedroot.proxywasm.Action;
import io.roastedroot.proxywasm.ChainedHandler;
Expand All @@ -10,18 +33,24 @@
import io.roastedroot.proxywasm.StreamType;
import io.roastedroot.proxywasm.WasmException;
import io.roastedroot.proxywasm.WasmResult;
import io.roastedroot.proxywasm.jaxrs.spi.HttpServer;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.core.Response;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

class HttpHandler extends ChainedHandler {

private final PluginHandler next;
private final HttpServer httpServer;
private final long startedAt;

HttpHandler(PluginHandler pluginHandler) {
HttpHandler(PluginHandler pluginHandler, HttpServer httpServer) {
this.next = pluginHandler;
this.httpServer = httpServer;
this.startedAt = System.currentTimeMillis();
}

@Override
Expand Down Expand Up @@ -237,11 +266,113 @@ public Action getAction() {

@Override
public byte[] getProperty(List<String> path) throws WasmException {

// Check to see if it's a well known property

// Downstream connection properties
if (CONNECTION_ID.equals(path)) {
// Do we need to generate one?
return null;
} else if (SOURCE_ADDRESS.equals(path)) {
return bytes(httpServer.remoteAddress());
} else if (SOURCE_PORT.equals(path)) {
return bytes(httpServer.remotePort());
} else if (DESTINATION_ADDRESS.equals(path)) {
return bytes(httpServer.localAddress());
} else if (DESTINATION_PORT.equals(path)) {
return bytes(httpServer.localPort());
}

// TLS connection properties
else if (CONNECTION_TLS_VERSION.equals(path)) {
return null;
} else if (CONNECTION_REQUESTED_SERVER_NAME.equals(path)) {
return null;
} else if (CONNECTION_MTLS.equals(path)) {
return null;
} else if (CONNECTION_SUBJECT_LOCAL_CERTIFICATE.equals(path)) {
return null;
} else if (CONNECTION_SUBJECT_PEER_CERTIFICATE.equals(path)) {
return null;
} else if (CONNECTION_DNS_SAN_LOCAL_CERTIFICATE.equals(path)) {
return null;
} else if (CONNECTION_DNS_SAN_PEER_CERTIFICATE.equals(path)) {
return null;
} else if (CONNECTION_URI_SAN_LOCAL_CERTIFICATE.equals(path)) {
return null;
} else if (CONNECTION_URI_SAN_PEER_CERTIFICATE.equals(path)) {
return null;
} else if (CONNECTION_SHA256_PEER_CERTIFICATE_DIGEST.equals(path)) {
return null;
}

// Upstream connection properties: we are not directly connecting to an upstream server, so
// these are not implemented.
// else if (UPSTREAM_ADDRESS.equals(path)) {
// return null;
// } else if (UPSTREAM_PORT.equals(path)) {
// return null;
// } else if (UPSTREAM_LOCAL_ADDRESS.equals(path)) {
// return null;
// } else if (UPSTREAM_LOCAL_PORT.equals(path)) {
// return null;
// } else if (UPSTREAM_TLS_VERSION.equals(path)) {
// return null;
// } else if (UPSTREAM_SUBJECT_LOCAL_CERTIFICATE.equals(path)) {
// return null;
// } else if (UPSTREAM_SUBJECT_PEER_CERTIFICATE.equals(path)) {
// return null;
// } else if (UPSTREAM_DNS_SAN_LOCAL_CERTIFICATE.equals(path)) {
// return null;
// } else if (UPSTREAM_DNS_SAN_PEER_CERTIFICATE.equals(path)) {
// return null;
// } else if (UPSTREAM_URI_SAN_LOCAL_CERTIFICATE.equals(path)) {
// return null;
// } else if (UPSTREAM_URI_SAN_PEER_CERTIFICATE.equals(path)) {
// return null;
// } else if (UPSTREAM_SHA256_PEER_CERTIFICATE_DIGEST.equals(path)) {
// return null;
// }

// HTTP request properties
else if (REQUEST_PROTOCOL.equals(path)) {
if (requestContext == null) {
return null;
}
return bytes(requestContext.getUriInfo().getRequestUri().getScheme());
} else if (REQUEST_TIME.equals(path)) {
// TODO: check encoding /w other impls
return bytes(new Date(startedAt).toString());
} else if (REQUEST_DURATION.equals(path)) {
// TODO: check encoding /w other impls
return bytes("" + (System.currentTimeMillis() - startedAt));
} else if (REQUEST_SIZE.equals(path)) {
if (httpRequestBody == null) {
return null;
}
// TODO: check encoding /w other impls
return bytes("" + httpRequestBody.length);
} else if (REQUEST_TOTAL_SIZE.equals(path)) {
return null;
}

// HTTP response properties
else if (RESPONSE_SIZE.equals(path)) {
if (httpResponseBody == null) {
return null;
}
// TODO: check encoding /w other impls
return bytes("" + httpResponseBody.length);
} else if (RESPONSE_TOTAL_SIZE.equals(path)) {
// TODO: how can we do this?
return null;
}

byte[] result = properties.get(path);
if (result == null) {
return next().getProperty(path);
if (result != null) {
return result;
}
return result;
return next().getProperty(path);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import io.roastedroot.proxywasm.Action;
import io.roastedroot.proxywasm.HttpContext;
import io.roastedroot.proxywasm.StartException;
import io.roastedroot.proxywasm.jaxrs.spi.HttpServer;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.container.ContainerRequestContext;
Expand All @@ -28,9 +30,12 @@ public class ProxyWasmFilter

private final WasmPluginFactory pluginFactory;

Instance<HttpServer> httpServer;

@Inject
public ProxyWasmFilter(WasmPluginFactory pluginFactory) {
public ProxyWasmFilter(WasmPluginFactory pluginFactory, Instance<HttpServer> httpServer) {
this.pluginFactory = pluginFactory;
this.httpServer = httpServer;
}

// TODO: the HttpContext and ProxyWasm object's should be closed once the request is done.
Expand All @@ -40,9 +45,9 @@ static class WasmHttpFilterContext {
final HttpHandler handler;
final HttpContext wasm;

public WasmHttpFilterContext(WasmPlugin plugin) {
public WasmHttpFilterContext(WasmPlugin plugin, HttpServer httpServer) {
this.pluginHandler = plugin.pluginHandler();
this.handler = new HttpHandler(plugin.pluginHandler());
this.handler = new HttpHandler(plugin.pluginHandler(), httpServer);
this.wasm = plugin.proxyWasm().createHttpContext(this.handler);
}
}
Expand All @@ -58,7 +63,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
}

var wasmHttpFilterContext = new WasmHttpFilterContext(plugin);
var wasmHttpFilterContext = new WasmHttpFilterContext(plugin, this.httpServer.get());
requestContext.setProperty(FILTER_CONTEXT_PROPERTY_NAME, wasmHttpFilterContext);

// the plugin may not be interested in the request headers.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.roastedroot.proxywasm.jaxrs;

import io.roastedroot.proxywasm.StartException;
import io.roastedroot.proxywasm.jaxrs.spi.HttpServer;
import jakarta.enterprise.inject.Any;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
Expand All @@ -15,6 +16,8 @@ public class WasmPluginFeature implements DynamicFeature {

private HashMap<String, WasmPluginFactory> plugins = new HashMap<>();

@Inject @Any Instance<HttpServer> requestAdaptor;

@Inject
public WasmPluginFeature(@Any Instance<WasmPluginFactory> factories) throws StartException {
for (var factory : factories) {
Expand All @@ -41,7 +44,7 @@ public void configure(ResourceInfo resourceInfo, FeatureContext context) {
if (pluignNameAnnotation != null) {
WasmPluginFactory factory = plugins.get(pluignNameAnnotation.value());
if (factory != null) {
context.register(new ProxyWasmFilter(factory));
context.register(new ProxyWasmFilter(factory, requestAdaptor));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.roastedroot.proxywasm.jaxrs.servlet;

import io.roastedroot.proxywasm.jaxrs.spi.HttpServer;
import jakarta.annotation.Priority;
import jakarta.enterprise.inject.Alternative;
import jakarta.enterprise.inject.Instance;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.core.Context;

@Alternative
@Priority(100)
public class ServletHttpServer implements HttpServer {

private final HttpServletRequest request;

public ServletHttpServer(@Context Instance<HttpServletRequest> request) {
this.request = request.get();
}

@Override
public String remoteAddress() {
return request.getRemoteAddr();
}

@Override
public String remotePort() {
return "" + request.getRemotePort();
}

@Override
public String localAddress() {
return request.getLocalAddr();
}

@Override
public String localPort() {
return "" + request.getLocalPort();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.roastedroot.proxywasm.jaxrs.spi;

/**
* This interface will help us deal with differences in the http server impl.
*/
public interface HttpServer {

String remoteAddress();

String remotePort();

String localAddress();

String localPort();
}
Loading
Loading