Skip to content

Instantly share code, notes, and snippets.

@rootsongjc
Last active December 17, 2024 11:44
Show Gist options
  • Save rootsongjc/418981d24478bb7060a30853d746cc21 to your computer and use it in GitHub Desktop.
Save rootsongjc/418981d24478bb7060a30853d746cc21 to your computer and use it in GitHub Desktop.
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: [ "*" ]
routes:
- match:
prefix: "/"
route:
host_rewrite_literal: www.envoyproxy.io
cluster: service_envoyproxy_io
http_filters:
- name: envoy.filters.http.ext_proc
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor
grpc_service:
envoy_grpc:
cluster_name: ext_proc_cluster
failure_mode_allow: true
processing_mode:
request_header_mode: SKIP
response_header_mode: SEND
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: ext_proc_cluster
connect_timeout: 0.25s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: ext_proc_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 9000
- name: service_envoyproxy_io
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
load_assignment:
cluster_name: service_envoyproxy_io
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: www.envoyproxy.io
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: www.envoyproxy.io
module ext_proc_demo
go 1.22.5
require (
github.com/envoyproxy/go-control-plane v0.13.1
google.golang.org/grpc v1.69.0
)
require (
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/protobuf v1.35.1 // indirect
)
package main
import (
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
configPb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
extProcPb "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3"
)
type extProcServer struct {
extProcPb.UnimplementedExternalProcessorServer
}
func (s *extProcServer) Process(
srv extProcPb.ExternalProcessor_ProcessServer,
) error {
for {
req, err := srv.Recv()
if err != nil {
return status.Errorf(codes.Unknown, "error receiving request: %v", err)
}
log.Printf("Received request: %+v\n", req)
// Prepare the response to be returned to Envoy.
resp := &extProcPb.ProcessingResponse{}
// Only process response headers, not request headers.
if respHeaders := req.GetResponseHeaders(); respHeaders != nil {
log.Println("Processing Response Headers...")
resp = &extProcPb.ProcessingResponse{
Response: &extProcPb.ProcessingResponse_ResponseHeaders{
ResponseHeaders: &extProcPb.HeadersResponse{
Response: &extProcPb.CommonResponse{
HeaderMutation: &extProcPb.HeaderMutation{
SetHeaders: []*configPb.HeaderValueOption{
{
Header: &configPb.HeaderValue{
Key: "x-extproc-hello",
Value: "Hello from ext_proc",
},
},
},
},
},
},
},
}
log.Printf("Sending response: %+v\n", resp)
// Send the response back to Envoy.
if err := srv.Send(resp); err != nil {
return status.Errorf(codes.Unknown, "error sending response: %v", err)
}
} else {
// If it is not a callback in the response header stage, do not make any modifications and continue processing the next event.
// For request_headers or other events, do not modify & ensure that Envoy will not be stuck.
// An empty processing can be returned for request_headers, or it can be skipped in envoy.yaml.
// Here, simply continue to wait for the next event.
continue
}
}
}
func main() {
lis, err := net.Listen("tcp", ":9000")
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
extProcPb.RegisterExternalProcessorServer(grpcServer, &extProcServer{})
log.Println("Starting gRPC server on :9000...")
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment