Skip to content
Closed
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ To build the project, you need to have Maven installed. You can build the projec
mvn clean install
```

## Quarkus Example
## Quarkus Example

The `quarkus-proxy-wasm-example` directory contains a simple example of how to use the proxy-wasm Java host with Quarkus.

Expand All @@ -35,7 +35,7 @@ public class Resources {
}
```

The `WasmPlugin` annotation is used to specify the name of the plugin to be used for filtering.
The `WasmPlugin` annotation is used to specify the name of the plugin to be used for filtering.

```java
package io.roastedroot.proxywasm.jaxrs.example;
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@
<modules>
<module>quarkus-proxy-wasm</module>
<module>quarkus-proxy-wasm-example</module>
<module>quarkus-x-corazawaf-example</module>
</modules>
</profile>
</profiles>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.roastedroot.proxywasm;

import com.dylibso.chicory.runtime.HostFunction;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
Expand Down Expand Up @@ -45,20 +47,31 @@ public static byte[] bytes(Duration value) {
}

public static byte[] bytes(int value) {
// TODO: test to check byte order
return new byte[] {
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value
};
return ByteBuffer.allocate(Integer.BYTES)
.order(ByteOrder.LITTLE_ENDIAN)
.putInt(value)
.array();
}

public static byte[] bytes(long value) {
return ByteBuffer.allocate(Long.BYTES)
.order(ByteOrder.LITTLE_ENDIAN)
.putLong(value)
.array();
}

public static int int32(byte[] bytes) {
if (bytes == null || bytes.length != 4) {
throw new IllegalArgumentException("Byte array must be exactly 4 bytes long");
}
return ((bytes[0] & 0xFF) << 24)
| ((bytes[1] & 0xFF) << 16)
| ((bytes[2] & 0xFF) << 8)
| (bytes[3] & 0xFF);
return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
}

public static long int64(byte[] bytes) {
if (bytes == null || bytes.length != 8) {
throw new IllegalArgumentException("Byte array must be exactly 8 bytes long");
}
return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getLong();
}

public static String string(byte[] value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ public interface LogHandler {

LogHandler DEFAULT = new LogHandler() {};

LogHandler SYSTEM =
new LogHandler() {
@Override
public void log(LogLevel level, String message) throws WasmException {
System.out.println(level + ": " + message);
}
};

default void log(LogLevel level, String message) throws WasmException {}

default LogLevel getLogLevel() throws WasmException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.roastedroot.proxywasm;

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
* A ProxyMap implementation that chains to another ProxyMap instance.
*/
public class SplitProxyMap implements ProxyMap {

private final ProxyMap primary;
private final ProxyMap secondary;

public SplitProxyMap(ProxyMap primary, ProxyMap secondary) {
this.primary = primary;
this.secondary = secondary;
}

@Override
public int size() {
return primary.size() + secondary.size();
}

@Override
public void add(String key, String value) {
secondary.add(key, value);
}

@Override
public void put(String key, String value) {
if (primary.get(key) != null) {
primary.put(key, value);
}
secondary.put(key, value);
}

@Override
public Iterable<? extends Map.Entry<String, String>> entries() {
return Stream.concat(
StreamSupport.stream(primary.entries().spliterator(), false),
StreamSupport.stream(secondary.entries().spliterator(), false))
.collect(Collectors.toList());
}

@Override
public String get(String key) {
String value = primary.get(key);
if (value != null) {
return value;
}
return secondary.get(key);
}

@Override
public void remove(String key) {
secondary.remove(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ private WellKnownHeaders() {}
public static final String AUTHORITY = ":authority";
public static final String PATH = ":path";
public static final String METHOD = ":method";
public static final String STATUS = ":status";
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,16 @@ public byte[] getHttpRequestBody() {
return httpRequestBody;
}

public void setHttpRequestBody(byte[] httpRequestBody) {
this.httpRequestBody = httpRequestBody;
}

public byte[] getHttpResponseBody() {
return httpResponseBody;
}

public void setHttpRequestBody(byte[] httpRequestBody) {
this.httpRequestBody = httpRequestBody;
public void setHttpResponseBody(byte[] httpResponseBody) {
this.httpResponseBody = httpResponseBody;
}

public byte[] getGrpcReceiveBuffer() {
Expand All @@ -111,10 +115,6 @@ public void setDownStreamData(byte[] downStreamData) {
this.downStreamData = downStreamData;
}

public void setHttpResponseBody(byte[] httpResponseBody) {
this.httpResponseBody = httpResponseBody;
}

public SendResponse getSendResponse() {
return sendResponse;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ public interface HttpRequestAdaptor {

String remoteAddress();

String remotePort();
int remotePort();

String localAddress();

String localPort();
int localPort();

String protocol();

ProxyMap getHttpRequestHeaders();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import io.roastedroot.proxywasm.WasmException;
import io.roastedroot.proxywasm.WasmResult;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -418,11 +417,8 @@ public int httpCall(

URI uri = null;
try {
uri =
URI.create(
new URI(scheme, null, authority, connectPort, null, null, null)
+ path);
} catch (IllegalArgumentException | URISyntaxException e) {
uri = URI.create(scheme + "://" + authority + path);
} catch (IllegalArgumentException e) {
throw new WasmException(WasmResult.BAD_ARGUMENT);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type httpCallTests struct {
}

func (
p *pluginContext) httpCallTests(contextID uint32) types.HttpContext {
p *pluginContext) httpCallTests(contextID uint32) types.HttpContext {
return &httpCallTests{
DefaultHttpContext: types.DefaultHttpContext{},
contextID: contextID,
Expand All @@ -42,12 +42,8 @@ func (

func (ctx *httpCallTests) OnHttpRequestHeaders(int, bool) types.Action {
proxywasm.LogDebug("OnHttpRequestHeaders")
var err error
ctx.headers, err = proxywasm.GetHttpRequestHeaders()
if err != nil {
proxywasm.LogCriticalf("failed to get request headers: %v", err)
}

ctx.headers = nil
method, err := proxywasm.GetProperty([]string{"request", "method"})
if err != nil {
proxywasm.LogCriticalf("failed to get request method: %v", err)
Expand All @@ -63,6 +59,11 @@ func (ctx *httpCallTests) OnHttpRequestHeaders(int, bool) types.Action {
path := gjson.Get(ctx.pluginContext.config, "path").Str
ctx.headers = append(ctx.headers, [2]string{":path", path})

requestHeaders, err := proxywasm.GetHttpRequestHeaders()
if err != nil {
proxywasm.LogCriticalf("failed to get request headers: %v", err)
}
ctx.headers = append(ctx.headers, requestHeaders...)
return types.ActionContinue
}

Expand Down
Binary file modified proxy-wasm-java-host/src/test/go-examples/unit_tester/main.wasm
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@
import static io.roastedroot.proxywasm.WellKnownProperties.SOURCE_ADDRESS;
import static io.roastedroot.proxywasm.WellKnownProperties.SOURCE_PORT;

import io.roastedroot.proxywasm.ArrayProxyMap;
import io.roastedroot.proxywasm.ProxyMap;
import io.roastedroot.proxywasm.SplitProxyMap;
import io.roastedroot.proxywasm.WasmException;
import io.roastedroot.proxywasm.WasmResult;
import io.roastedroot.proxywasm.WellKnownHeaders;
import io.roastedroot.proxywasm.WellKnownProperties;
import io.roastedroot.proxywasm.plugin.HttpContext;
import io.roastedroot.proxywasm.plugin.HttpRequestAdaptor;
Expand Down Expand Up @@ -84,8 +87,8 @@ public String remoteAddress() {
}

@Override
public String remotePort() {
return "";
public int remotePort() {
return 0;
}

@Override
Expand All @@ -94,8 +97,20 @@ public String localAddress() {
}

@Override
public String localPort() {
return "";
public int localPort() {
return 0;
}

@Override
public String protocol() {
String protocol = requestContext.getUriInfo().getRequestUri().getScheme();
if (protocol == null) {
protocol = "HTTP";
}
protocol = protocol.toUpperCase();
// technically it should be something like "HTTP/1.1" or "HTTP/2" (but JAX-RS doesn't give
// us that info).
return protocol;
}

// //////////////////////////////////////////////////////////////////////
Expand All @@ -104,7 +119,21 @@ public String localPort() {

@Override
public ProxyMap getHttpRequestHeaders() {
return new MultivaluedMapAdaptor<>(requestContext.getHeaders());
URI requestUri = requestContext.getUriInfo().getRequestUri();
ArrayProxyMap wellKnownHeaders = new ArrayProxyMap();
wellKnownHeaders.add(WellKnownHeaders.AUTHORITY, requestUri.getAuthority());
wellKnownHeaders.add(WellKnownHeaders.SCHEME, requestUri.getScheme());
wellKnownHeaders.add(WellKnownHeaders.METHOD, requestContext.getMethod());
var path = requestUri.getRawPath();
if (path == null) {
path = "";
}
if (requestUri.getRawQuery() != null) {
path += "?" + requestUri.getRawQuery();
}
wellKnownHeaders.add(WellKnownHeaders.PATH, path);
return new SplitProxyMap(
wellKnownHeaders, new MultivaluedMapAdaptor<>(requestContext.getHeaders()));
}

@Override
Expand All @@ -114,7 +143,10 @@ public ProxyMap getHttpRequestTrailers() {

@Override
public ProxyMap getHttpResponseHeaders() {
return new MultivaluedMapAdaptor<>(responseContext.getHeaders());
ArrayProxyMap wellKnownHeaders = new ArrayProxyMap();
wellKnownHeaders.add(WellKnownHeaders.STATUS, "" + responseContext.getStatus());
return new SplitProxyMap(
wellKnownHeaders, new MultivaluedMapAdaptor<>(responseContext.getHeaders()));
}

@Override
Expand Down Expand Up @@ -144,11 +176,17 @@ public byte[] getProperty(HttpContext pluginRequest, List<String> path) throws W
} else if (SOURCE_ADDRESS.equals(path)) {
return bytes(remoteAddress());
} else if (SOURCE_PORT.equals(path)) {
return bytes(remotePort());
// Port attribute is populated as uint64 (8 byte)
// Ref:
// https://github.com/envoyproxy/envoy/blob/1b3da361279a54956f01abba830fc5d3a5421828/source/common/network/utility.cc#L201
return bytes((long) remotePort());
} else if (DESTINATION_ADDRESS.equals(path)) {
return bytes(localAddress());
} else if (DESTINATION_PORT.equals(path)) {
return bytes(localPort());
// Port attribute is populated as uint64 (8 byte)
// Ref:
// https://github.com/envoyproxy/envoy/blob/1b3da361279a54956f01abba830fc5d3a5421828/source/common/network/utility.cc#L201
return bytes((long) localPort());
}

// TODO: get TLS connection properties
Expand Down Expand Up @@ -248,10 +286,7 @@ else if (WellKnownProperties.CONNECTION_TLS_VERSION.equals(path)) {

// HTTP request properties
else if (REQUEST_PROTOCOL.equals(path)) {
if (requestContext == null) {
return null;
}
return bytes(requestContext.getUriInfo().getRequestUri().getScheme());
return bytes(protocol());
} else if (REQUEST_TIME.equals(path)) {
return bytes(new Date(startedAt));
} else if (REQUEST_DURATION.equals(path)) {
Expand Down
Loading
Loading