Skip to content

Commit 4cf9533

Browse files
authored
Adds support for all headers getter in experimental Go SDK (#28)
1 parent a99fb81 commit 4cf9533

File tree

3 files changed

+84
-4
lines changed

3 files changed

+84
-4
lines changed

go/gosdk/abi.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,28 @@ void envoy_dynamic_module_callback_http_send_response(
9797
uintptr_t filter_envoy_ptr, uint32_t status_code,
9898
uintptr_t headers_vector, size_t headers_vector_size,
9999
uintptr_t body, size_t body_length);
100+
101+
#cgo noescape envoy_dynamic_module_callback_http_get_request_headers_count
102+
#cgo nocallback envoy_dynamic_module_callback_http_get_request_headers_count
103+
size_t envoy_dynamic_module_callback_http_get_request_headers_count(
104+
uintptr_t filter_envoy_ptr);
105+
106+
#cgo noescape envoy_dynamic_module_callback_http_get_request_headers
107+
#cgo nocallback envoy_dynamic_module_callback_http_get_request_headers
108+
bool envoy_dynamic_module_callback_http_get_request_headers(
109+
uintptr_t filter_envoy_ptr,
110+
uintptr_t* result_headers);
111+
112+
#cgo noescape envoy_dynamic_module_callback_http_get_request_headers_count
113+
#cgo nocallback envoy_dynamic_module_callback_http_get_request_headers_count
114+
size_t envoy_dynamic_module_callback_http_get_response_headers_count(
115+
uintptr_t filter_envoy_ptr);
116+
117+
#cgo noescape envoy_dynamic_module_callback_http_get_request_headers
118+
#cgo nocallback envoy_dynamic_module_callback_http_get_request_headers
119+
bool envoy_dynamic_module_callback_http_get_response_headers(
120+
uintptr_t filter_envoy_ptr,
121+
uintptr_t* result_headers);
100122
*/
101123
import "C"
102124

@@ -320,7 +342,7 @@ func (e envoyFilter) SetResponseHeader(key string, value []byte) bool {
320342

321343
// bodyReader implements [io.Reader] for the request or response body.
322344
type bodyReader struct {
323-
chunks []bodyChunk
345+
chunks []envoySlice
324346
index, offset int
325347
}
326348

@@ -345,14 +367,58 @@ func (b *bodyReader) Read(p []byte) (n int, err error) {
345367
return n, nil
346368
}
347369

348-
type bodyChunk struct {
370+
type envoySlice struct {
349371
data uintptr
350372
length C.size_t
351373
}
352374

353375
// envoyFilter implements [EnvoyHttpFilter].
354376
type envoyFilter struct{ raw uintptr }
355377

378+
// GetRequestHeaders implements EnvoyHttpFilter.
379+
func (e envoyFilter) GetRequestHeaders() map[string][]string {
380+
count := C.envoy_dynamic_module_callback_http_get_request_headers_count(C.uintptr_t(e.raw))
381+
raw := make([][2]envoySlice, count)
382+
ret := C.envoy_dynamic_module_callback_http_get_request_headers(
383+
C.uintptr_t(e.raw),
384+
(*C.uintptr_t)(unsafe.Pointer(&raw[0])),
385+
)
386+
if !ret {
387+
return nil
388+
}
389+
// Copy the headers to a Go slice.
390+
headers := make(map[string][]string, count) // The count is the number of (key, value) pairs, so this might be larger than the number of unique names.
391+
for i := range count {
392+
// Copy the Envoy owner data to a Go string.
393+
key := string(unsafe.Slice((*byte)(unsafe.Pointer(raw[i][0].data)), raw[i][0].length))
394+
value := string(unsafe.Slice((*byte)(unsafe.Pointer(raw[i][1].data)), raw[i][1].length))
395+
headers[key] = append(headers[key], value)
396+
}
397+
return headers
398+
}
399+
400+
// GetResponseHeaders implements [EnvoyHttpFilter].
401+
func (e envoyFilter) GetResponseHeaders() map[string][]string {
402+
count := C.envoy_dynamic_module_callback_http_get_response_headers_count(C.uintptr_t(e.raw))
403+
raw := make([][2]envoySlice, count)
404+
ret := C.envoy_dynamic_module_callback_http_get_response_headers(
405+
C.uintptr_t(e.raw),
406+
(*C.uintptr_t)(unsafe.Pointer(&raw[0])),
407+
)
408+
if !ret {
409+
return nil
410+
}
411+
// Copy the headers to a Go slice.
412+
headers := make(map[string][]string, count) // The count is the number of (key, value) pairs, so this might be larger than the number of unique names.
413+
for i := range count {
414+
// Copy the Envoy owner data to a Go string.
415+
key := string(unsafe.Slice((*byte)(unsafe.Pointer(raw[i][0].data)), raw[i][0].length))
416+
value := string(unsafe.Slice((*byte)(unsafe.Pointer(raw[i][1].data)), raw[i][1].length))
417+
headers[key] = append(headers[key], value)
418+
}
419+
return headers
420+
}
421+
356422
// SendLocalReply implements EnvoyHttpFilter.
357423
func (e envoyFilter) SendLocalReply(statusCode uint32, headers [][2]string, body []byte) {
358424
headersVecPtr := uintptr(unsafe.Pointer(unsafe.SliceData(headers)))
@@ -403,7 +469,7 @@ func (e envoyFilter) GetRequestBody() (io.Reader, bool) {
403469
return nil, false
404470
}
405471

406-
chunks := make([]bodyChunk, vectorSize)
472+
chunks := make([]envoySlice, vectorSize)
407473
ret = C.envoy_dynamic_module_callback_http_get_request_body_vector(
408474
C.uintptr_t(e.raw),
409475
(*C.uintptr_t)(unsafe.Pointer(&chunks[0])),
@@ -445,7 +511,7 @@ func (e envoyFilter) GetResponseBody() (io.Reader, bool) {
445511
if !ret {
446512
return nil, false
447513
}
448-
chunks := make([]bodyChunk, vectorSize)
514+
chunks := make([]envoySlice, vectorSize)
449515
ret = C.envoy_dynamic_module_callback_http_get_response_body_vector(
450516
C.uintptr_t(e.raw),
451517
(*C.uintptr_t)(unsafe.Pointer(&chunks[0])),

go/gosdk/gosdk.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ type HttpFilterConfig interface {
3030
type EnvoyHttpFilter interface {
3131
// GetRequestHeader gets the first value of the request header. Returns the value and true if the header is found.
3232
GetRequestHeader(key string) (string, bool)
33+
// GetRequestHeaders gets all the request headers.
34+
GetRequestHeaders() map[string][]string
3335
// SetRequestHeader sets the request header. Returns true if the header is set successfully.
3436
SetRequestHeader(key string, value []byte) bool
3537
// GetResponseHeader gets the first value of the response header. Returns the value and true if the header is found.
3638
GetResponseHeader(key string) (string, bool)
39+
// GetResponseHeaders gets all the response headers.
40+
GetResponseHeaders() map[string][]string
3741
// SetResponseHeader sets the response header. Returns true if the header is set successfully.
3842
SetResponseHeader(key string, value []byte) bool
3943
// GetRequestBody gets the request body. Returns the io.Reader and true if the body is found.

go/passthrough.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ func (p passthroughFilter) RequestHeaders(e gosdk.EnvoyHttpFilter, endOfStream b
2828
fooValue, _ := e.GetRequestHeader("foo")
2929
fmt.Printf("gosdk: RequestHeaders, foo: %v\n", fooValue)
3030
fmt.Printf("gosdk: RequestHeaders, endOfStream: %v\n", endOfStream)
31+
for k, vs := range e.GetRequestHeaders() {
32+
for _, v := range vs {
33+
fmt.Printf("gosdk: RequestHeaders, header: %s: %s\n", k, v)
34+
}
35+
}
3136
return gosdk.RequestHeadersStatusContinue
3237
}
3338

@@ -86,6 +91,11 @@ func (p passthroughFilter) ResponseHeaders(e gosdk.EnvoyHttpFilter, endOfStream
8691
}
8792
fmt.Printf("gosdk: ResponseHeaders, status: %v\n", status)
8893
e.SetResponseHeader("x-passthrough-response-header", []byte("true"))
94+
for k, vs := range e.GetResponseHeaders() {
95+
for _, v := range vs {
96+
fmt.Printf("gosdk: ResponseHeaders, header: %s: %s\n", k, v)
97+
}
98+
}
8999
return gosdk.ResponseHeadersStatusContinue
90100
}
91101

0 commit comments

Comments
 (0)