Wasm C++ 过滤器

此沙盒演示了用 C++ 编写的基本 Envoy Wasm 过滤器,它将内容注入 HTTP 响应的正文,并添加和更新某些标头。

它还会指导您完成构建自己的 C++ Wasm 过滤器 并使用 Envoy 运行它的步骤。

步骤 1:启动所有容器

首先,让我们启动容器 - 一个使用 Wasm 过滤器的 Envoy 代理,以及一个将我们的请求回显的后台服务器。Envoy 配置公开了两个监听器,第一个监听器在端口 8000 上,它在监听器过滤器链中包含 wasm 过滤器。第二个监听器在端口 8001 上监听,路由到一个包含上游 wasm 过滤器的集群。

更改到 Envoy 存储库中的 examples/wasm-cc 文件夹,并启动组合

$ pwd
envoy/examples/wasm-cc
$ docker compose pull
$ docker compose up --build -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, 0.0.0.0:8001->8001/tcp
wasm_web_service_1   node ./index.js                Up

步骤 2:检查 Web 响应

当您向代理发出请求时,Wasm 过滤器应在响应正文末尾注入“Hello, world”。

$ curl -s https://127.0.0.1:8000 | grep "Hello, world"
}Hello, world

过滤器还会将 content-type 标头设置为 text/plain,并添加自定义 x-wasm-custom 标头。

$ curl -v https://127.0.0.1:8000 | grep "content-type: "
content-type: text/plain; charset=utf-8

$ curl -v https://127.0.0.1:8000 | grep "x-wasm-custom: "
x-wasm-custom: FOO

在第二个监听器路由到具有上游 wasm 过滤器的集群时,可以获得类似的输出。

$ curl -s https://127.0.0.1:8001 | grep "Hello, world"
}Hello, world

$ curl -v https://127.0.0.1:8001 | grep "content-type: "
content-type: text/plain; charset=utf-8

$ curl -v https://127.0.0.1:8001 | grep "x-wasm-custom: "
x-wasm-custom: FOO

步骤 3:编译更新的过滤器

为 Wasm 过滤器提供了两个源代码文件。

envoy_filter_http_wasm_example.cc 提供了包含的预构建二进制文件的源代码。

envoy_filter_http_wasm_updated_example.cc 对原始文件进行了一些更改。

以下 diff 显示了所做的更改

--- /tmp/tmpiw2hzbvp/generated/rst/start/sandboxes/_include/wasm-cc/envoy_filter_http_wasm_example.cc
+++ /tmp/tmpiw2hzbvp/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;
 }
 

警告

这些编译更新 Wasm 二进制文件的说明使用 envoyproxy/envoy-build-ubuntu 镜像。您将需要 4-5 GB 的磁盘空间来容纳此镜像。

导出来自主机系统的 UID。这将确保在构建容器内创建的二进制文件与您的主机用户具有相同的权限

$ export UID

注意

构建组合旨在以类似于 Envoy 存储库中的 ./ci/run_envoy_docker.sh 命令的方式工作。

Bazel 临时工件是在 /tmp/envoy-docker-build 中创建的,其 uid 来自 UID 环境变量。

停止代理服务器并使用更新的代码编译 Wasm 二进制文件

$ docker compose stop proxy
$ docker compose -f docker-compose-wasm.yaml up --remove-orphans wasm_compile_update

编译后的二进制文件现在应该在 lib 文件夹中。

$ 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

步骤 4:编辑 Dockerfile 并重启代理

编辑示例中提供的 Dockerfile-proxy 食谱,以使用您在步骤 3 中创建的更新的二进制文件。

找到将 Wasm 二进制文件添加到镜像的 COPY

1FROM envoyproxy/envoy:dev
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"]

将此行替换为以下内容

COPY ./lib/envoy_filter_http_wasm_updated_example.wasm /lib/envoy_filter_http_wasm_example.wasm

现在,重建并启动代理容器。

$ docker compose up --build -d proxy

步骤 5:检查代理是否已更新

Wasm 过滤器应在响应正文末尾注入“Hello, Wasm world”。

$ curl -s https://127.0.0.1:8000 | grep "Hello, Wasm world"
}Hello, Wasm world

content-typex-wasm-custom 标头也应该已更改

$ curl -v https://127.0.0.1:8000 | grep "content-type: "
content-type: text/html; charset=utf-8

$ curl -v https://127.0.0.1:8000 | grep "x-wasm-custom: "
x-wasm-custom: BAR

另请参阅

Envoy Wasm 过滤器

有关 Envoy Wasm 过滤器的更多信息。

Envoy Wasm API(V3)

Envoy Wasm API - 版本 3。

代理 Wasm C++ SDK

用于代理的 WebAssembly(C++ SDK)