diff --git a/src/main/java/io/roastedroot/proxywasm/ABI.java b/src/main/java/io/roastedroot/proxywasm/ABI.java index 1f461fa..ff9003e 100644 --- a/src/main/java/io/roastedroot/proxywasm/ABI.java +++ b/src/main/java/io/roastedroot/proxywasm/ABI.java @@ -1,6 +1,8 @@ package io.roastedroot.proxywasm; +import static io.roastedroot.proxywasm.Helpers.bytes; import static io.roastedroot.proxywasm.Helpers.replaceBytes; +import static io.roastedroot.proxywasm.Helpers.split; import static io.roastedroot.proxywasm.Helpers.string; import com.dylibso.chicory.experimental.hostmodule.annotations.HostModule; @@ -11,7 +13,7 @@ import com.dylibso.chicory.runtime.WasmRuntimeException; import com.dylibso.chicory.wasm.InvalidException; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Map; @HostModule("env") @@ -221,15 +223,6 @@ private byte[] readMemory(int address, int len) throws WasmException { } } - private String readString(int address, int len) throws WasmException { - var data = readMemory(address, len); - return new String(data, StandardCharsets.UTF_8); - } - - private void copyIntoInstance(String value, int retPtr, int retSize) throws WasmException { - copyIntoInstance(value.getBytes(), retPtr, retSize); - } - private void copyIntoInstance(byte[] value, int retPtr, int retSize) throws WasmException { try { if (value.length != 0) { @@ -402,7 +395,7 @@ boolean proxyOnConfigure(int arg0, int arg1) { int proxyLog(int logLevel, int messageData, int messageSize) { try { var msg = memory.readBytes(messageData, messageSize); - handler.log(LogLevel.fromInt(logLevel), new String(msg)); + handler.log(LogLevel.fromInt(logLevel), string(msg)); return WasmResult.OK.getValue(); } catch (WasmException e) { return e.result().getValue(); @@ -840,7 +833,7 @@ int proxyGetHeaderMapValue( } // Get key from memory - String key = readString(keyDataPtr, keySize); + String key = string(readMemory(keyDataPtr, keySize)); // Get value from map String value = headerMap.get(key); @@ -849,7 +842,7 @@ int proxyGetHeaderMapValue( } // Copy value into WebAssembly memory - copyIntoInstance(value, valueDataPtr, valueSize); + copyIntoInstance(bytes(value), valueDataPtr, valueSize); return WasmResult.OK.getValue(); } catch (WasmRuntimeException e) { @@ -898,10 +891,10 @@ int proxyReplaceHeaderMapValue( } // Get key from memory - String key = readString(keyDataPtr, keySize); + String key = string(readMemory(keyDataPtr, keySize)); // Get value from memory - String value = readString(valueDataPtr, valueSize); + String value = string(readMemory(valueDataPtr, valueSize)); // Replace value in map var copy = new ArrayProxyMap(headerMap); @@ -936,7 +929,7 @@ int proxyRemoveHeaderMapValue(int mapType, int keyDataPtr, int keySize) { } // Get key from memory - String key = readString(keyDataPtr, keySize); + String key = string(readMemory(keyDataPtr, keySize)); if (key.isEmpty()) { return WasmResult.BAD_ARGUMENT.getValue(); } @@ -1075,11 +1068,11 @@ private ProxyMap decodeMap(int addr, int mem_size) throws WasmException { } // Extract key - String key = readString((int) (addr + dataOffset), (int) keySize); + String key = string(readMemory((int) (addr + dataOffset), (int) keySize)); dataOffset += keySize + 1; // Skip null terminator // Extract value - String value = readString((int) (addr + dataOffset), (int) valueSize); + String value = string(readMemory((int) (addr + dataOffset), (int) valueSize)); dataOffset += valueSize + 1; // Add to result map @@ -1620,7 +1613,18 @@ int proxyGetSharedData( return WasmResult.NOT_FOUND.getValue(); } - copyIntoInstance(value.data, returnValueData, returnValueSize); + try { + if (value.data.length != 0) { + int addr = malloc(value.data.length); + putMemory(addr, value.data); + putUint32(returnValueData, addr); + } else { + putUint32(returnValueData, 0); + } + putUint32(returnValueSize, value.data.length); + } catch (WasmException e) { + throw new WasmException(WasmResult.INVALID_MEMORY_ACCESS); + } putUint32(returnCas, value.cas); return WasmResult.OK.getValue(); @@ -1642,10 +1646,13 @@ int proxyRegisterSharedQueue(int queueNameDataPtr, int queueNameSize, int return // Get queue name from memory String queueName = string(readMemory(queueNameDataPtr, queueNameSize)); - var vmId = handler.getProperty("vm_id"); + var vmId = handler.getProperty(List.of("vm_id")); + if (vmId == null) { + return WasmResult.INTERNAL_FAILURE.getValue(); + } // Register shared queue using handler - int queueId = handler.registerSharedQueue(new QueueName(vmId, queueName)); + int queueId = handler.registerSharedQueue(new QueueName(string(vmId), queueName)); putUint32(returnQueueId, queueId); return WasmResult.OK.getValue(); @@ -1710,7 +1717,18 @@ int proxyDequeueSharedQueue(int queueId, int returnValueData, int returnValueSiz return WasmResult.EMPTY.getValue(); } - copyIntoInstance(value, returnValueData, returnValueSize); + try { + if (value.length != 0) { + int addr = malloc(value.length); + putMemory(addr, value); + putUint32(returnValueData, addr); + } else { + putUint32(returnValueData, 0); + } + putUint32(returnValueSize, value.length); + } catch (WasmException e) { + throw new WasmException(WasmResult.INVALID_MEMORY_ACCESS); + } return WasmResult.OK.getValue(); } catch (WasmException e) { @@ -1811,10 +1829,10 @@ int proxyGetProperty(int keyPtr, int keySize, int returnValueData, int returnVal return WasmResult.BAD_ARGUMENT.getValue(); } - String key = new String(keyBytes); + var path = split(string(keyBytes), '\u0000'); // Get property value using handler - String value = handler.getProperty(key); + byte[] value = handler.getProperty(path); if (value == null) { return WasmResult.NOT_FOUND.getValue(); } @@ -1834,10 +1852,10 @@ int proxyGetProperty(int keyPtr, int keySize, int returnValueData, int returnVal int proxySetProperty(int pathDataPtr, int pathSize, int valueDataPtr, int valueSize) { try { // Get key from memory - String path = string(readMemory(pathDataPtr, pathSize)); + var path = split(string(readMemory(pathDataPtr, pathSize)), '\u0000'); // Get value from memory - String value = string(readMemory(valueDataPtr, valueSize)); + var value = readMemory(valueDataPtr, valueSize); // Set property value using handler WasmResult result = handler.setProperty(path, value); diff --git a/src/main/java/io/roastedroot/proxywasm/ChainedHandler.java b/src/main/java/io/roastedroot/proxywasm/ChainedHandler.java index 255eef2..ddb68da 100644 --- a/src/main/java/io/roastedroot/proxywasm/ChainedHandler.java +++ b/src/main/java/io/roastedroot/proxywasm/ChainedHandler.java @@ -1,5 +1,7 @@ package io.roastedroot.proxywasm; +import java.util.List; + /** * A Handler implementation that chains to another handler if it can't handle the request. */ @@ -103,10 +105,15 @@ public WasmResult setGrpcReceiveTrailerMetaData(ProxyMap metadata) { } @Override - public String getProperty(String key) throws WasmException { + public byte[] getProperty(List key) throws WasmException { return next().getProperty(key); } + @Override + public WasmResult setProperty(List path, byte[] value) { + return next().setProperty(path, value); + } + @Override public byte[] getHttpRequestBody() { return next().getHttpRequestBody(); @@ -324,11 +331,6 @@ public LogLevel getLogLevel() throws WasmException { return next().getLogLevel(); } - @Override - public WasmResult setProperty(String path, String value) { - return next().setProperty(path, value); - } - @Override public int grpcCall( String upstreamName, diff --git a/src/main/java/io/roastedroot/proxywasm/Handler.java b/src/main/java/io/roastedroot/proxywasm/Handler.java index 73594db..1557aec 100644 --- a/src/main/java/io/roastedroot/proxywasm/Handler.java +++ b/src/main/java/io/roastedroot/proxywasm/Handler.java @@ -1,5 +1,7 @@ package io.roastedroot.proxywasm; +import java.util.List; + public interface Handler { default void log(LogLevel level, String message) throws WasmException {} @@ -45,11 +47,11 @@ default ProxyMap getCustomHeaders(int mapType) { return null; } - default String getProperty(String key) throws WasmException { + default byte[] getProperty(List key) throws WasmException { return null; } - default WasmResult setProperty(String path, String value) { + default WasmResult setProperty(List path, byte[] value) { return WasmResult.UNIMPLEMENTED; } diff --git a/src/main/java/io/roastedroot/proxywasm/Helpers.java b/src/main/java/io/roastedroot/proxywasm/Helpers.java index e71f4ba..eeaa3e2 100644 --- a/src/main/java/io/roastedroot/proxywasm/Helpers.java +++ b/src/main/java/io/roastedroot/proxywasm/Helpers.java @@ -2,7 +2,9 @@ import com.dylibso.chicory.runtime.HostFunction; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Map; public final class Helpers { @@ -30,6 +32,20 @@ public static String string(byte[] value) { return new String(value, StandardCharsets.UTF_8); } + public static List split(String str, char separator) { + ArrayList parts = new ArrayList<>(); + int start = 0; + int len = str.length(); + for (int i = 0; i < len; i++) { + if (str.charAt(i) == separator) { + parts.add(str.substring(start, i)); + start = i + 1; + } + } + parts.add(str.substring(start)); // Add the last part + return List.copyOf(parts); + } + public static int len(byte[] value) { if (value == null) { return 0; diff --git a/src/main/java/io/roastedroot/proxywasm/ProxyWasm.java b/src/main/java/io/roastedroot/proxywasm/ProxyWasm.java index dbee2d8..760429f 100644 --- a/src/main/java/io/roastedroot/proxywasm/ProxyWasm.java +++ b/src/main/java/io/roastedroot/proxywasm/ProxyWasm.java @@ -26,7 +26,6 @@ public final class ProxyWasm implements Closeable { private final Handler pluginHandler; private final byte[] pluginConfig; private final byte[] vmConfig; - private final HashMap properties; private final WasiPreview1 wasi; private final AtomicInteger nextContextID = new AtomicInteger(1); @@ -42,7 +41,6 @@ public final class ProxyWasm implements Closeable { private ProxyWasm(Builder other) throws StartException { this.vmConfig = other.vmConfig; this.pluginConfig = other.pluginConfig; - this.properties = Objects.requireNonNullElse(other.properties, new HashMap<>()); this.pluginHandler = Objects.requireNonNullElse(other.pluginHandler, new Handler() {}); this.wasi = other.wasi; this.abi = other.abi; @@ -91,19 +89,6 @@ public byte[] getPluginConfig() { return pluginConfig; } - @Override - public String getProperty(String key) throws WasmException { - if (properties.containsKey(key)) { - return properties.get(key); - } - - var handler = activeContext.handler(); - if (handler != null) { - return handler.getProperty(key); - } - return null; - } - @Override public WasmResult setEffectiveContextID(int contextID) { Context context = contexts.get(contextID); @@ -188,24 +173,6 @@ public void tick() { this.abi.proxyOnTick(pluginContext.id()); } - public void setProperty(String[] path, String data) { - if (len(path) == 0) { - throw new IllegalArgumentException("path must not be empty"); - } - if (len(data) == 0) { - throw new IllegalArgumentException("data must not be empty"); - } - - this.properties.put(String.join("\u0000", path), data); - } - - public String getProperty(String[] path) { - if (len(path) == 0) { - throw new IllegalArgumentException("path must not be empty"); - } - return this.properties.get(String.join("\u0000", path)); - } - @Override public void close() { this.pluginContext.close(); @@ -262,7 +229,6 @@ public static class Builder implements Cloneable { private byte[] vmConfig = new byte[0]; private byte[] pluginConfig = new byte[0]; - private HashMap properties; private Handler pluginHandler; private ImportMemory memory; private WasiOptions wasiOptions; @@ -301,15 +267,6 @@ public ProxyWasm.Builder withPluginConfig(String pluginConfig) { return this; } - public ProxyWasm.Builder withProperties(Map properties) { - if (properties != null) { - this.properties = new HashMap<>(properties); - } else { - this.properties = null; - } - return this; - } - public ProxyWasm.Builder withPluginHandler(Handler vmHandler) { this.pluginHandler = vmHandler; return this; diff --git a/src/test/java/io/roastedroot/proxywasm/examples/MockHandler.java b/src/test/java/io/roastedroot/proxywasm/examples/MockHandler.java index 9205968..a0a1dd8 100644 --- a/src/test/java/io/roastedroot/proxywasm/examples/MockHandler.java +++ b/src/test/java/io/roastedroot/proxywasm/examples/MockHandler.java @@ -461,4 +461,17 @@ public WasmResult setAction(StreamType streamType, Action action) { public Action getAction() { return action; } + + final HashMap, byte[]> properties = new HashMap<>(); + + @Override + public byte[] getProperty(List path) throws WasmException { + return properties.get(path); + } + + @Override + public WasmResult setProperty(List path, byte[] value) { + properties.put(path, value); + return WasmResult.OK; + } } diff --git a/src/test/java/io/roastedroot/proxywasm/examples/OnRequestHeadersTest.java b/src/test/java/io/roastedroot/proxywasm/examples/OnRequestHeadersTest.java index 2b09a29..1cd2f34 100644 --- a/src/test/java/io/roastedroot/proxywasm/examples/OnRequestHeadersTest.java +++ b/src/test/java/io/roastedroot/proxywasm/examples/OnRequestHeadersTest.java @@ -1,5 +1,6 @@ package io.roastedroot.proxywasm.examples; +import static io.roastedroot.proxywasm.Helpers.bytes; import static org.junit.jupiter.api.Assertions.assertEquals; import com.dylibso.chicory.wasm.Parser; @@ -22,10 +23,9 @@ public class OnRequestHeadersTest { public void test() throws StartException { // This module uses the 0_1_0 ABI var handler = new MockHandler(); - ProxyWasm.Builder builder = - ProxyWasm.builder() - .withProperties(Map.of("plugin_root_id", "")) - .withPluginHandler(handler); + handler.setProperty(List.of("plugin_root_id"), bytes("")); + + ProxyWasm.Builder builder = ProxyWasm.builder().withPluginHandler(handler); try (var proxyWasm = builder.build(module)) { diff --git a/src/test/java/io/roastedroot/proxywasm/examples/PropertiesTest.java b/src/test/java/io/roastedroot/proxywasm/examples/PropertiesTest.java index 13be5ba..8c9e594 100644 --- a/src/test/java/io/roastedroot/proxywasm/examples/PropertiesTest.java +++ b/src/test/java/io/roastedroot/proxywasm/examples/PropertiesTest.java @@ -1,6 +1,8 @@ package io.roastedroot.proxywasm.examples; import static io.roastedroot.proxywasm.Helpers.append; +import static io.roastedroot.proxywasm.Helpers.bytes; +import static io.roastedroot.proxywasm.Helpers.string; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -10,7 +12,10 @@ import io.roastedroot.proxywasm.Action; import io.roastedroot.proxywasm.ProxyWasm; import io.roastedroot.proxywasm.StartException; +import io.roastedroot.proxywasm.WasmException; import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -33,7 +38,7 @@ public class PropertiesTest { @BeforeEach void setUp() throws StartException { this.handler = new MockHandler(); - ProxyWasm.Builder builder = ProxyWasm.builder(); + ProxyWasm.Builder builder = ProxyWasm.builder().withPluginHandler(this.handler); this.proxyWasm = builder.build(module); } @@ -55,12 +60,14 @@ public void routeIsUnauthenticated() { } @Test - public void userIsAuthenticated() { + public void userIsAuthenticated() throws WasmException { var path = "auth"; - var data = "cookie"; - proxyWasm.setProperty(append(propertyPrefix, path), data); - var actualData = proxyWasm.getProperty(append(propertyPrefix, path)); + var data = bytes("cookie"); + + List key = Arrays.asList(append(propertyPrefix, path)); + handler.setProperty(key, data); + var actualData = handler.getProperty(key); assertEquals(data, actualData); int id = 0; @@ -72,16 +79,20 @@ public void userIsAuthenticated() { } handler.assertLogsEqual( - String.format("auth header is \"%s\"", data), String.format("%d finished", id)); + String.format("auth header is \"%s\"", string(data)), + String.format("%d finished", id)); } @Test - public void userIsUnauthenticated() { + public void userIsUnauthenticated() throws WasmException { var path = "auth"; - var data = "cookie"; - proxyWasm.setProperty(append(propertyPrefix, path), data); - var actualData = proxyWasm.getProperty(append(propertyPrefix, path)); + var data = bytes("cookie"); + + List key = Arrays.asList(append(propertyPrefix, path)); + + handler.setProperty(key, data); + var actualData = handler.getProperty(key); assertEquals(data, actualData); try (var host = proxyWasm.createHttpContext(handler)) { diff --git a/src/test/java/io/roastedroot/proxywasm/examples/RustEnvoyFilterMetadataTest.java b/src/test/java/io/roastedroot/proxywasm/examples/RustEnvoyFilterMetadataTest.java new file mode 100644 index 0000000..39c828a --- /dev/null +++ b/src/test/java/io/roastedroot/proxywasm/examples/RustEnvoyFilterMetadataTest.java @@ -0,0 +1,51 @@ +package io.roastedroot.proxywasm.examples; + +import static io.roastedroot.proxywasm.Helpers.bytes; +import static io.roastedroot.proxywasm.Helpers.string; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.dylibso.chicory.wasm.Parser; +import com.dylibso.chicory.wasm.WasmModule; +import io.roastedroot.proxywasm.ProxyMap; +import io.roastedroot.proxywasm.ProxyWasm; +import io.roastedroot.proxywasm.StartException; +import java.nio.file.Path; +import java.util.List; +import org.junit.jupiter.api.Test; + +/** + * Test loading https://github.com/proxy-wasm/proxy-wasm-rust-sdk/tree/c8b2335df66a569a6306c58e346dd0cf9dbc0f3a/examples/envoy_filter_metadata + */ +public class RustEnvoyFilterMetadataTest { + private static final WasmModule module = + Parser.parse(Path.of("./src/test/rust-examples/envoy_filter_metadata/main.wasm")); + + @Test + public void test() throws StartException { + var handler = new MockHandler(); + try (var host = ProxyWasm.builder().withPluginHandler(handler).build(module)) { + + String value = "SOME-VALUE"; + handler.setProperty( + List.of( + "metadata", + "filter_metadata", + "envoy.filters.http.lua", + "uppercased-custom-metadata"), + bytes(value)); + try (var context = host.createHttpContext(handler)) { + context.callOnRequestHeaders(true); + MockHandler.HttpResponse response = handler.getSentHttpResponse(); + assertNotNull(response); + assertEquals(200, response.statusCode); + assertEquals( + ProxyMap.of("Powered-By", "proxy-wasm", "uppercased-metadata", value), + response.headers); + assertEquals( + String.format("Custom response with Envoy metadata: \"%s\"\n", value), + string(response.body)); + } + } + } +} diff --git a/src/test/java/io/roastedroot/proxywasm/examples/RustHelloWorldTest.java b/src/test/java/io/roastedroot/proxywasm/examples/RustHelloWorldTest.java index a2103cf..bb70676 100644 --- a/src/test/java/io/roastedroot/proxywasm/examples/RustHelloWorldTest.java +++ b/src/test/java/io/roastedroot/proxywasm/examples/RustHelloWorldTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.dylibso.chicory.wasm.Parser; +import com.dylibso.chicory.wasm.WasmModule; import io.roastedroot.proxywasm.ProxyWasm; import io.roastedroot.proxywasm.StartException; import java.nio.file.Path; @@ -12,11 +13,12 @@ * Test loading https://github.com/proxy-wasm/proxy-wasm-rust-sdk/tree/c8b2335df66a569a6306c58e346dd0cf9dbc0f3a/examples/hello_world */ public class RustHelloWorldTest { + private static final WasmModule module = + Parser.parse(Path.of("./src/test/rust-examples/hello_world/main.wasm")); @Test - public void pauseUntilEOS() throws StartException { + public void test() throws StartException { var handler = new MockHandler(); - var module = Parser.parse(Path.of("./src/test/rust-examples/hello_world/main.wasm")); try (var host = ProxyWasm.builder().withPluginHandler(handler).build(module)) { handler.assertLogsEqual("Hello, World!"); diff --git a/src/test/java/io/roastedroot/proxywasm/examples/SharedQueueTest.java b/src/test/java/io/roastedroot/proxywasm/examples/SharedQueueTest.java index 08452bc..4fb8b73 100644 --- a/src/test/java/io/roastedroot/proxywasm/examples/SharedQueueTest.java +++ b/src/test/java/io/roastedroot/proxywasm/examples/SharedQueueTest.java @@ -1,5 +1,6 @@ package io.roastedroot.proxywasm.examples; +import static io.roastedroot.proxywasm.Helpers.bytes; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -15,6 +16,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -55,11 +57,11 @@ public void testOnPluginStart() throws StartException, WasmException { // Create and configure the http_request_headers receiver instance var receiverHandler1 = new MockHandler(sharedData); + receiverHandler1.setProperty(List.of("vm_id"), bytes(receiverVmId)); var receiverHost1 = deferClose( ProxyWasm.builder() .withPluginHandler(receiverHandler1) - .withProperties(Map.of("vm_id", receiverVmId)) .withPluginConfig("http_request_headers") .build(receiverModule)); @@ -74,11 +76,11 @@ public void testOnPluginStart() throws StartException, WasmException { // Create and configure the http_response_headers receiver instance var receiverHandler2 = new MockHandler(sharedData); + receiverHandler2.setProperty(List.of("vm_id"), bytes(receiverVmId)); var receiverHost2 = deferClose( ProxyWasm.builder() .withPluginHandler(receiverHandler2) - .withProperties(Map.of("vm_id", receiverVmId)) .withPluginConfig("http_response_headers") .build(receiverModule)); @@ -96,11 +98,11 @@ public void testOnPluginStart() throws StartException, WasmException { // Create and configure the sender instance var senderHandler = new MockHandler(sharedData); var senderVmId = "sender"; + senderHandler.setProperty(List.of("vm_id"), bytes(senderVmId)); var senderHost = deferClose( ProxyWasm.builder() .withPluginHandler(senderHandler) - .withProperties(Map.of("vm_id", senderVmId)) .withPluginConfig("http") .build(senderModule)); senderHandler.assertLogsContain( diff --git a/src/test/java/io/roastedroot/proxywasm/examples/VmPluginConfigurationTest.java b/src/test/java/io/roastedroot/proxywasm/examples/VmPluginConfigurationTest.java index 28fd4b4..5ea95d3 100644 --- a/src/test/java/io/roastedroot/proxywasm/examples/VmPluginConfigurationTest.java +++ b/src/test/java/io/roastedroot/proxywasm/examples/VmPluginConfigurationTest.java @@ -1,5 +1,6 @@ package io.roastedroot.proxywasm.examples; +import static io.roastedroot.proxywasm.Helpers.bytes; import static org.junit.jupiter.api.Assertions.assertEquals; import com.dylibso.chicory.wasm.Parser; @@ -8,7 +9,6 @@ import io.roastedroot.proxywasm.StartException; import java.nio.file.Path; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.Test; /** @@ -22,11 +22,11 @@ public class VmPluginConfigurationTest { @Test public void test() throws StartException { var handler = new MockHandler(); + handler.setProperty(List.of("plugin_name"), bytes("vm_plugin_configuration")); ProxyWasm.Builder builder = ProxyWasm.builder() .withPluginConfig("plugin_config") .withVmConfig("vm_config") - .withProperties(Map.of("plugin_name", "vm_plugin_configuration")) .withPluginHandler(handler); try (var ignored = builder.build(module)) { diff --git a/src/test/rust-examples/envoy_filter_metadata/Cargo.lock b/src/test/rust-examples/envoy_filter_metadata/Cargo.lock new file mode 100644 index 0000000..6012ca0 --- /dev/null +++ b/src/test/rust-examples/envoy_filter_metadata/Cargo.lock @@ -0,0 +1,127 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "log" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" + +[[package]] +name = "once_cell" +version = "1.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proxy-wasm" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14a5a4df5a1ab77235e36a0a0f638687ee1586d21ee9774037693001e94d4e11" +dependencies = [ + "hashbrown", + "log", +] + +[[package]] +name = "proxy-wasm-example-envoy-filter-metadata" +version = "0.0.1" +dependencies = [ + "proxy-wasm", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/src/test/rust-examples/envoy_filter_metadata/Cargo.toml b/src/test/rust-examples/envoy_filter_metadata/Cargo.toml new file mode 100644 index 0000000..0852ad3 --- /dev/null +++ b/src/test/rust-examples/envoy_filter_metadata/Cargo.toml @@ -0,0 +1,21 @@ +[package] +publish = false +name = "proxy-wasm-example-envoy-filter-metadata" +version = "0.0.1" +authors = ["Martijn Swaagma "] +description = "Proxy-Wasm plugin example: Envoy filter metadata" +license = "Apache-2.0" +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +proxy-wasm = "0.2.2" + +[profile.release] +lto = true +opt-level = 3 +codegen-units = 1 +panic = "abort" +strip = "debuginfo" diff --git a/src/test/rust-examples/envoy_filter_metadata/README.md b/src/test/rust-examples/envoy_filter_metadata/README.md new file mode 100644 index 0000000..6dc4984 --- /dev/null +++ b/src/test/rust-examples/envoy_filter_metadata/README.md @@ -0,0 +1,5 @@ +## Attribution + +This example originally came from: +https://github.com/proxy-wasm/proxy-wasm-rust-sdk/tree/c8b2335df66a569a6306c58e346dd0cf9dbc0f3a/examples/envoy_filter_metadata +``` diff --git a/src/test/rust-examples/envoy_filter_metadata/main.wasm b/src/test/rust-examples/envoy_filter_metadata/main.wasm new file mode 100755 index 0000000..0596707 Binary files /dev/null and b/src/test/rust-examples/envoy_filter_metadata/main.wasm differ diff --git a/src/test/rust-examples/envoy_filter_metadata/src/lib.rs b/src/test/rust-examples/envoy_filter_metadata/src/lib.rs new file mode 100644 index 0000000..e5f1905 --- /dev/null +++ b/src/test/rust-examples/envoy_filter_metadata/src/lib.rs @@ -0,0 +1,52 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use proxy_wasm::traits::*; +use proxy_wasm::types::*; + +proxy_wasm::main! {{ + proxy_wasm::set_log_level(LogLevel::Trace); + proxy_wasm::set_http_context(|_, _| -> Box { Box::new(MetadataHttp {}) }); +}} + +struct MetadataHttp {} + +impl Context for MetadataHttp {} + +impl HttpContext for MetadataHttp { + fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action { + // Read data set by the lua filter + match self.get_property(vec![ + "metadata", + "filter_metadata", + "envoy.filters.http.lua", + "uppercased-custom-metadata", + ]) { + Some(metadata) => match String::from_utf8(metadata) { + Ok(data) => { + self.send_http_response( + 200, + vec![("Powered-By", "proxy-wasm"), ("uppercased-metadata", &data)], + Some( + format!("Custom response with Envoy metadata: {:?}\n", data).as_bytes(), + ), + ); + Action::Pause + } + _ => Action::Continue, + }, + _ => Action::Continue, + } + } +}