Wasm C++ filter
Requirements
Setup your sandbox environment with Docker and Docker Compose, and clone the Envoy repository with Git.
Used to make HTTP
requests.
Compatibility
The provided Wasm binary was compiled for the x86_64
architecture. If you would like to use this sandbox with the arm64
architecture, change directory to examples/wasm-cc
and skip to Step 3.
This sandbox demonstrates a basic Envoy Wasm filter written in C++ which injects content into the body of an HTTP
response, and adds and updates some headers.
It also takes you through the steps required to build your own C++ Wasm filter, and run it with Envoy.
Step 1: Start all of our containers
First lets start the containers - an Envoy proxy which uses a Wasm Filter, and a backend which echos back our request.
Change to the examples/wasm-cc
folder in the Envoy repo, and start the composition:
$ pwd
envoy/examples/wasm-cc
$ docker-compose build --pull
$ docker-compose up -d
$ docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------------------
wasm_proxy_1 /docker-entrypoint.sh /usr ... Up 10000/tcp, 0.0.0.0:8000->8000/tcp
wasm_web_service_1 node ./index.js Up
Step 2: Check web response
The Wasm filter should inject “Hello, world” at the end of the response body when you make a request to the proxy.
$ curl -s http://localhost:8000 | grep "Hello, world"
}Hello, world
The filter also sets the content-type
header to text/plain
, and adds a custom x-wasm-custom
header.
$ curl -v http://localhost:8000 | grep "content-type: "
content-type: text/plain; charset=utf-8
$ curl -v http://localhost:8000 | grep "x-wasm-custom: "
x-wasm-custom: FOO
Step 3: Compile the updated filter
There are two source code files provided for the Wasm filter.
envoy_filter_http_wasm_example.cc provides the source code for the included prebuilt binary.
envoy_filter_http_wasm_updated_example.cc makes a few changes to the original.
The following diff shows the changes that have been made:
--- /tmp/tmpe5xv7v2q/generated/rst/start/sandboxes/_include/wasm-cc/envoy_filter_http_wasm_example.cc
+++ /tmp/tmpe5xv7v2q/generated/rst/start/sandboxes/_include/wasm-cc/envoy_filter_http_wasm_updated_example.cc
@@ -65,8 +65,8 @@
for (auto& p : pairs) {
LOG_INFO(std::string(p.first) + std::string(" -> ") + std::string(p.second));
}
- addResponseHeader("X-Wasm-custom", "FOO");
- replaceResponseHeader("content-type", "text/plain; charset=utf-8");
+ addResponseHeader("X-Wasm-custom", "BAR");
+ replaceResponseHeader("content-type", "text/html; charset=utf-8");
removeResponseHeader("content-length");
return FilterHeadersStatus::Continue;
}
@@ -78,9 +78,9 @@
return FilterDataStatus::Continue;
}
-FilterDataStatus ExampleContext::onResponseBody(size_t body_buffer_length,
+FilterDataStatus ExampleContext::onResponseBody(size_t /* body_buffer_length */,
bool /* end_of_stream */) {
- setBuffer(WasmBufferType::HttpResponseBody, 0, body_buffer_length, "Hello, world\n");
+ setBuffer(WasmBufferType::HttpResponseBody, 0, 17, "Hello, Wasm world");
return FilterDataStatus::Continue;
}
Warning
These instructions for compiling an updated Wasm binary use the envoyproxy/envoy-build-ubuntu image. You will need 4-5GB of disk space to accommodate this image.
Stop the proxy server and compile the Wasm binary with the updated code:
$ docker-compose stop proxy
$ docker-compose -f docker-compose-wasm.yaml up --remove-orphans wasm_compile_update
The compiled binary should now be in the lib
folder.
$ ls -l lib
total 120
-r-xr-xr-x 1 root root 59641 Oct 20 00:00 envoy_filter_http_wasm_example.wasm
-r-xr-xr-x 1 root root 59653 Oct 20 10:16 envoy_filter_http_wasm_updated_example.wasm
Step 4: Edit the Dockerfile and restart the proxy
Edit the Dockerfile-proxy
recipe provided in the example to use the updated binary you created in step 3.
Find the COPY
line that adds the Wasm binary to the image:
1FROM envoyproxy/envoy-dev:latest
2COPY ./envoy.yaml /etc/envoy.yaml
3COPY ./lib/envoy_filter_http_wasm_example.wasm /lib/envoy_filter_http_wasm_example.wasm
4RUN chmod go+r /etc/envoy.yaml /lib/envoy_filter_http_wasm_example.wasm
5CMD ["/usr/local/bin/envoy", "-c", "/etc/envoy.yaml", "--service-cluster", "proxy"]
Replace this line with the following:
COPY ./lib/envoy_filter_http_wasm_updated_example.wasm /lib/envoy_filter_http_wasm_example.wasm
Now, rebuild and start the proxy container.
$ docker-compose up --build -d proxy
Step 5: Check the proxy has been updated
The Wasm filter should instead inject “Hello, Wasm world” at the end of the response body.
$ curl -s http://localhost:8000 | grep "Hello, Wasm world"
}Hello, Wasm world
The content-type
and x-wasm-custom
headers should also have changed
$ curl -v http://localhost:8000 | grep "content-type: "
content-type: text/html; charset=utf-8
$ curl -v http://localhost:8000 | grep "x-wasm-custom: "
x-wasm-custom: BAR
See also
Further information about the Envoy Wasm filter.
The Envoy Wasm API - version 3.
WebAssembly for proxies (C++ SDK)