From f95589b09d0d4abbba3f348655ac593b118b1b97 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 23 Apr 2025 17:05:08 -0400 Subject: [PATCH 1/4] Change version to 999-SNAPSHOT. Signed-off-by: Hiram Chirino --- pom.xml | 2 +- proxy-wasm-java-host/pom.xml | 2 +- proxy-wasm-jaxrs/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 64fee35..e0428dd 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.roastedroot proxy-wasm-java-host-parent - 1.0-SNAPSHOT + 999-SNAPSHOT pom proxy-wasm-java-host-parent diff --git a/proxy-wasm-java-host/pom.xml b/proxy-wasm-java-host/pom.xml index d2a16fb..3ec1f8b 100644 --- a/proxy-wasm-java-host/pom.xml +++ b/proxy-wasm-java-host/pom.xml @@ -5,7 +5,7 @@ io.roastedroot proxy-wasm-java-host-parent - 1.0-SNAPSHOT + 999-SNAPSHOT ../pom.xml diff --git a/proxy-wasm-jaxrs/pom.xml b/proxy-wasm-jaxrs/pom.xml index 4cc0fac..44d626c 100644 --- a/proxy-wasm-jaxrs/pom.xml +++ b/proxy-wasm-jaxrs/pom.xml @@ -5,7 +5,7 @@ io.roastedroot proxy-wasm-java-host-parent - 1.0-SNAPSHOT + 999-SNAPSHOT ../pom.xml From 86c502d72dcb4529243075e972111571999cd590 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 23 Apr 2025 16:58:04 -0400 Subject: [PATCH 2/4] Make context tacking more robust. Signed-off-by: Hiram Chirino --- .../proxywasm/jaxrs/WasmPluginFilter.java | 123 ++++++++++++------ 1 file changed, 80 insertions(+), 43 deletions(-) diff --git a/proxy-wasm-jaxrs/src/main/java/io/roastedroot/proxywasm/jaxrs/WasmPluginFilter.java b/proxy-wasm-jaxrs/src/main/java/io/roastedroot/proxywasm/jaxrs/WasmPluginFilter.java index f469840..aba496d 100644 --- a/proxy-wasm-jaxrs/src/main/java/io/roastedroot/proxywasm/jaxrs/WasmPluginFilter.java +++ b/proxy-wasm-jaxrs/src/main/java/io/roastedroot/proxywasm/jaxrs/WasmPluginFilter.java @@ -19,7 +19,10 @@ import jakarta.ws.rs.ext.WriterInterceptorContext; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Implements the JAX-RS {@link ContainerRequestFilter}, {@link ContainerResponseFilter}, @@ -37,8 +40,10 @@ */ public class WasmPluginFilter implements ContainerRequestFilter, WriterInterceptor, ContainerResponseFilter { - private static final String FILTER_CONTEXT_PROPERTY_NAME = - PluginHttpContext.class.getName() + ":"; + + private static final String FILTER_CONTEXT = PluginHttpContext.class.getName() + ".context"; + + private static final Logger LOGGER = Logger.getLogger(WasmPluginFilter.class.getName()); private final List pluginPools; @@ -52,6 +57,22 @@ public WasmPluginFilter(List pluginPools) { this.pluginPools = List.copyOf(pluginPools); } + private static class FilterContext { + final Pool pool; + final Plugin plugin; + final PluginHttpContext httpContext; + + FilterContext(Pool pool, Plugin plugin, PluginHttpContext httpContext) { + this.pool = pool; + this.plugin = plugin; + this.httpContext = httpContext; + } + + public void release() { + pool.release(plugin); + } + } + /** * Intercepts incoming JAX-RS requests before they reach the resource method. * @@ -65,34 +86,51 @@ public WasmPluginFilter(List pluginPools) { */ @Override public void filter(ContainerRequestContext requestContext) throws IOException { + + ArrayList filterContexts = new ArrayList<>(); + requestContext.setProperty(FILTER_CONTEXT, filterContexts); for (var pluginPool : pluginPools) { - filter(requestContext, pluginPool); + try { + Plugin plugin = pluginPool.borrow(); + plugin.lock(); + try { + var serverAdaptor = plugin.getServerAdaptor(); + var requestAdaptor = + (JaxrsHttpRequestAdaptor) + serverAdaptor.httpRequestAdaptor(requestContext); + requestAdaptor.setRequestContext(requestContext); + var httpContext = plugin.createHttpContext(requestAdaptor); + filterContexts.add(new FilterContext(pluginPool, plugin, httpContext)); + } finally { + plugin.unlock(); + } + } catch (StartException e) { + LOGGER.log(Level.SEVERE, "Failed to start plugin: " + pluginPool.name(), e); + + // release any plugins that were borrowed before the exception + for (var filterContext : filterContexts) { + filterContext.release(); + } + filterContexts.clear(); + requestContext.abortWith(internalServerError()); + return; + } + } + for (var filterContext : filterContexts) { + filter(requestContext, filterContext); } } - private void filter(ContainerRequestContext requestContext, Pool pluginPool) + private void filter(ContainerRequestContext requestContext, FilterContext filterContext) throws IOException { - Plugin plugin; - try { - plugin = pluginPool.borrow(); - } catch (StartException e) { - requestContext.abortWith(interalServerError()); - return; - } - plugin.lock(); + var httpContext = filterContext.httpContext; + httpContext.plugin().lock(); try { - var requestAdaptor = - (JaxrsHttpRequestAdaptor) - plugin.getServerAdaptor().httpRequestAdaptor(requestContext); - var httpContext = plugin.createHttpContext(requestAdaptor); - requestContext.setProperty( - FILTER_CONTEXT_PROPERTY_NAME + pluginPool.name(), httpContext); // the plugin may not be interested in the request headers. if (httpContext.context().hasOnRequestHeaders()) { - requestAdaptor.setRequestContext(requestContext); var action = httpContext.context().callOnRequestHeaders(false); if (action == Action.PAUSE) { httpContext.maybePause(); @@ -135,11 +173,11 @@ private void filter(ContainerRequestContext requestContext, Pool pluginPool) } } finally { - plugin.unlock(); // allow another request to use the plugin. + httpContext.plugin().unlock(); // allow another request to use the plugin. } } - private static Response interalServerError() { + private static Response internalServerError() { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -160,23 +198,23 @@ private static Response interalServerError() { public void filter( ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { - for (var pluginPool : pluginPools) { - filter(requestContext, responseContext, pluginPool); + var filterContexts = (ArrayList) requestContext.getProperty(FILTER_CONTEXT); + if (filterContexts == null) { + return; + } + + for (var filterContext : filterContexts) { + filter(requestContext, responseContext, filterContext); } } private void filter( ContainerRequestContext requestContext, ContainerResponseContext responseContext, - Pool pluginPool) + FilterContext filterContext) throws IOException { - var httpContext = - (PluginHttpContext) - requestContext.getProperty( - FILTER_CONTEXT_PROPERTY_NAME + pluginPool.name()); - if (httpContext == null) { - throw new WebApplicationException(interalServerError()); - } + + var httpContext = filterContext.httpContext; // the plugin may not be interested in the request headers. if (httpContext.context().hasOnResponseHeaders()) { @@ -251,6 +289,11 @@ private void filter( public void aroundWriteTo(WriterInterceptorContext ctx) throws IOException, WebApplicationException { + var filterContexts = (ArrayList) ctx.getProperty(FILTER_CONTEXT); + if (filterContexts == null) { + return; + } + try { var original = ctx.getOutputStream(); @@ -260,13 +303,8 @@ public void aroundWriteTo(WriterInterceptorContext ctx) byte[] bytes = baos.toByteArray(); - for (var pluginPool : pluginPools) { - var httpContext = - (PluginHttpContext) - ctx.getProperty(FILTER_CONTEXT_PROPERTY_NAME + pluginPool.name()); - if (httpContext == null) { - throw new WebApplicationException(interalServerError()); - } + for (var filterContext : List.copyOf(filterContexts)) { + var httpContext = filterContext.httpContext; httpContext.plugin().lock(); @@ -296,10 +334,9 @@ public void aroundWriteTo(WriterInterceptorContext ctx) original.write(bytes); } finally { - for (var pluginPool : pluginPools) { - var httpContext = - (PluginHttpContext) - ctx.getProperty(FILTER_CONTEXT_PROPERTY_NAME + pluginPool.name()); + for (var filterContext : List.copyOf(filterContexts)) { + + var httpContext = filterContext.httpContext; // allow other request to use the plugin. httpContext.context().close(); @@ -307,7 +344,7 @@ public void aroundWriteTo(WriterInterceptorContext ctx) // TODO: will aroundWriteTo always get called so that we can avoid leaking the // plugin? - pluginPool.release(httpContext.plugin()); + filterContext.release(); } } } From 86d277865b8674d0df3616e08b3574f34858c79f Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Thu, 24 Apr 2025 08:38:23 -0400 Subject: [PATCH 3/4] Switch to SNAPSHOT version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e0428dd..1c76db0 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 5.12.0 - 1.1.0 + 999-SNAPSHOT 3.1.10 11.0.25 From 5d2fc2b71db35e08f0b4d9014000068224344140 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Tue, 29 Apr 2025 13:47:01 -0400 Subject: [PATCH 4/4] Bump chicory version. Signed-off-by: Hiram Chirino --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1c76db0..647ec7d 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 5.12.0 - 999-SNAPSHOT + 1.3.0 3.1.10 11.0.25