Golang HTTP TCP Bridge

This bridge enables an HTTP client to connect to a TCP server via a Golang plugin, facilitating Protocol Convert from HTTP to any RPC protocol in Envoy.

Note

The bridge is designed for sync-data-flow between go and c, so when you create new goroutines, DO NOT touch the request in these goroutines, they could be background goroutines.

The Bridge allows Golang to be run during both the request and response flows of upstream.

Go plugins used by this bridge can be recompiled independently of Envoy.

See the Envoy’s Golang HTTP-TCP Bridge proposal for more details on the bridge’s implementation.

Developing a Go plugin

Envoy’s Golang HTTP-TCP Bridge plugin must implement the HttpTcpBridge API.

Here is the introduction about the HttpTcpBridge API:

  • EncodeHeaders: get HTTP request headers and decide whether to directly send RPC frame to TCP server.

  • EncodeData: get HTTP request body and convert it to RPC frame, then send that to TCP server. and you can control whether to half-close the upstream connection by Envoy.

  • OnUpstreamData: aggregate and verify multiple RPC frames from the TCP server, then convert the complete RPC frame to the HTTP body, finally construct the HTTP response with headers for the HTTP client.

Attention

The Go plugin API is not yet stable, you are strongly recommended to use the same version of Go plugin SDK and Envoy.

When you are using a release version of Envoy, i.e. 1.26.x, you should use github.com/envoyproxy/envoy v1.26.x in the go.mod file.

When you are not using a release, i.e. the latest main branch of Envoy, you could use go get -u github.com/envoyproxy/envoy@SHA to get the same version of the Go plugin SDK, the SHA is the latest commit SHA.

Building a Go plugin

Attention

When building a Go plugin dynamic library, you must use a Go version consistent with Envoy’s version of glibc.

One way to ensure a compatible Go version is to use the Go binary provided by Envoy’s bazel setup:

$ bazel run @go_sdk//:bin/go -- version
...
go version goX.YZ linux/amd64

For example, to build the .so for a foo plugin, you might run:

$ bazel run @go_sdk//:bin/go build -- --buildmode=c-shared  -v -o path/to/output/libfoo.so path/to/src/foo

Configuration

Tip

This bridge should be configured with the type URL type.googleapis.com/envoy.extensions.upstreams.http.tcp.golang.v3alpha.Config.

A prebuilt Golang HTTP TCP Bridge my_bridge.so might be configured as follows:

35    lb_policy: round_robin
36    upstream_config:
37      name: envoy.upstreams.http.tcp.golang
38      typed_config:
39        "@type": type.googleapis.com/envoy.extensions.upstreams.http.tcp.golang.v3alpha.Config
40        library_id: my-bridge-id
41        library_path: "lib/my_bridge.so"
42        plugin_name: my_bridge
43    load_assignment:
44      cluster_name: local_service
45      endpoints:

Extensible plugin configuration

Envoy’s Go plugins can specify and use their own configuration.

Below is a very simple example of how such a plugin might be configured in Envoy:

35    lb_policy: round_robin
36    upstream_config:
37      name: envoy.upstreams.http.tcp.golang
38      typed_config:
39        "@type": type.googleapis.com/envoy.extensions.upstreams.http.tcp.golang.v3alpha.Config
40        library_id: my-configurable-bridge-id
41        library_path: "lib/my_configurable_bridge.so"
42        plugin_name: my_configurable_bridge
43        plugin_config:
44          "@type": type.googleapis.com/xds.type.v3.TypedStruct
45          value:
46            foo: "bar"
47    load_assignment:
48      cluster_name: local_service
49      endpoints:

See the HttpTcpBridge API for more information about how the plugin’s configuration data can be accessed.