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.