C++ HTTP filter (statically linked)

This sandbox demonstrates how to build a native C++ HTTP filter and statically link it into the Envoy binary using bzlmod.

The example filter is a decoder filter which reads a key and val from its configuration, and adds them as a header to proxied requests.

Note

This example uses a custom extensions_build_config.

While this is not strictly necessary to build a custom module, it allows you to control what is included in the built Envoy binary.

In this case, it excludes Wasm from the build:

1# Drop all wasm extensions (filters, runtimes, access logger, stat sink, bootstrap).
2EXTENSIONS = {
3    name: target
4    for name, target in _EXTENSIONS.items()
5    if "wasm" not in name
6}

Step 1: Build the Envoy binary with the filter

Export UID from your host system. This will ensure that the binary created inside the build container has the same permissions as your host user:

$ export UID

Change to the filter-cc directory and build the Envoy binary with the sample filter statically linked:

$ pwd
examples/filter-cc
$ docker compose -f docker-compose-build.yaml run --remove-orphans filter_build

The built binary should now be in the bin folder.

$ ls -l bin
total 803408
-r-xr-xr-x 1 user user 822683320 Oct 20 10:16 envoy

Step 2: Start all of our containers

Start the composition - an Envoy proxy which uses the binary built in Step 1, and a backend which echos back our request:

$ pwd
examples/filter-cc
$ docker compose up --build -d
$ docker compose ps

NAME                       COMMAND                  SERVICE       STATUS    PORTS
filter-cc-proxy-1          "/usr/local/bin/envo…"   proxy         running   0.0.0.0:8000->8000/tcp
filter-cc-web_service-1    "/bin/echo-server"       web_service   running   8080/tcp

Step 3: Check the filter has added its header

The sample filter is configured in envoy.yaml to add a via: sample-filter header to proxied requests:

26          http_filters:
27          - name: sample
28            typed_config:
29              "@type": type.googleapis.com/sample.Decoder
30              key: via
31              val: sample-filter

As the backend service echos the request it receives, the header added by the filter should be visible in the response body:

$ curl -s http://localhost:8000 | grep "sample-filter"
Via: sample-filter

Step 4: Run the integration test

The example also provides an integration test which exercises the filter inside Envoy’s HTTP integration test framework, without the need to build - or run - the Envoy binary:

$ pwd
examples/filter-cc
$ docker compose -f docker-compose-build.yaml run --remove-orphans filter_test

See also

HTTP filters

Further information about Envoy’s HTTP filters.