Skip to content

Commit 3ecccc8

Browse files
authored
Fixes reentrance issue on SendLocalReply (#33)
#25 --------- Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
1 parent a2c1f19 commit 3ecccc8

3 files changed

Lines changed: 39 additions & 24 deletions

File tree

go/gosdk/abi.go

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ bool envoy_dynamic_module_callback_http_get_response_body_vector_size(
9292
uintptr_t filter_envoy_ptr, size_t* size);
9393
9494
#cgo noescape envoy_dynamic_module_callback_http_send_response
95-
#cgo nocallback envoy_dynamic_module_callback_http_send_response
95+
// Uncomment once https://github.com/envoyproxy/envoy/pull/39206 is merged.
96+
// #cgo nocallback envoy_dynamic_module_callback_http_send_response
9697
void envoy_dynamic_module_callback_http_send_response(
9798
uintptr_t filter_envoy_ptr, uint32_t status_code,
9899
uintptr_t headers_vector, size_t headers_vector_size,
@@ -219,10 +220,7 @@ func envoy_dynamic_module_on_http_filter_request_body(
219220
}
220221

221222
//export envoy_dynamic_module_on_http_filter_request_trailers
222-
func envoy_dynamic_module_on_http_filter_request_trailers(
223-
filterEnvoyPtr uintptr,
224-
filterModulePtr uintptr,
225-
) uintptr {
223+
func envoy_dynamic_module_on_http_filter_request_trailers(uintptr, uintptr) uintptr {
226224
return 0
227225
}
228226

@@ -249,18 +247,12 @@ func envoy_dynamic_module_on_http_filter_response_body(
249247
}
250248

251249
//export envoy_dynamic_module_on_http_filter_response_trailers
252-
func envoy_dynamic_module_on_http_filter_response_trailers(
253-
filterEnvoyPtr uintptr,
254-
filterModulePtr uintptr,
255-
) uintptr {
250+
func envoy_dynamic_module_on_http_filter_response_trailers(uintptr, uintptr) uintptr {
256251
return 0
257252
}
258253

259254
//export envoy_dynamic_module_on_http_filter_stream_complete
260-
func envoy_dynamic_module_on_http_filter_stream_complete(
261-
filterEnvoyPtr uintptr,
262-
filterModulePtr uintptr,
263-
) {
255+
func envoy_dynamic_module_on_http_filter_stream_complete(uintptr, uintptr) {
264256
}
265257

266258
// GetRequestHeader implements [EnvoyHttpFilter].

go/header_auth.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ type (
1414
authHeaderName string
1515
}
1616
// headerAuthFilter implements [gosdk.HttpFilter].
17-
headerAuthFilter struct{ authHeaderName string }
17+
headerAuthFilter struct {
18+
authHeaderName string
19+
sendOnResponseHeaderPhase bool
20+
}
1821
)
1922

2023
// Destroy implements [gosdk.HttpFilterConfig].
@@ -26,29 +29,34 @@ func (p headerAuthFilterConfig) NewFilter() gosdk.HttpFilter {
2629
}
2730

2831
// Destroy implements [gosdk.HttpFilter].
29-
func (p headerAuthFilter) Destroy() {}
32+
func (p *headerAuthFilter) Destroy() {}
3033

3134
// RequestHeaders implements [gosdk.HttpFilter].
32-
func (p headerAuthFilter) RequestHeaders(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.RequestHeadersStatus {
33-
_, ok := e.GetRequestHeader(p.authHeaderName)
35+
func (p *headerAuthFilter) RequestHeaders(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.RequestHeadersStatus {
36+
v, ok := e.GetRequestHeader(p.authHeaderName)
3437
if !ok {
35-
e.SendLocalReply(http.StatusUnauthorized, [][2]string{{"Content-Type", "text/plain"}}, []byte("Unauthorized by Go Module\n"))
38+
e.SendLocalReply(http.StatusUnauthorized, [][2]string{{"Content-Type", "text/plain"}}, []byte("Unauthorized by Go Module at on_request_headers\n"))
3639
return gosdk.RequestHeadersStatusStopIteration
3740
}
41+
p.sendOnResponseHeaderPhase = v == "on_response_headers"
3842
return gosdk.RequestHeadersStatusContinue
3943
}
4044

4145
// RequestBody implements [gosdk.HttpFilter].
42-
func (p headerAuthFilter) RequestBody(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.RequestBodyStatus {
46+
func (p *headerAuthFilter) RequestBody(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.RequestBodyStatus {
4347
return gosdk.RequestBodyStatusContinue
4448
}
4549

4650
// ResponseHeaders implements [gosdk.HttpFilter].
47-
func (p headerAuthFilter) ResponseHeaders(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.ResponseHeadersStatus {
51+
func (p *headerAuthFilter) ResponseHeaders(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.ResponseHeadersStatus {
52+
if p.sendOnResponseHeaderPhase {
53+
e.SendLocalReply(http.StatusUnauthorized, [][2]string{{"Content-Type", "text/plain"}}, []byte("Unauthorized by Go Module at on_response_headers\n"))
54+
return gosdk.ResponseHeadersStatusStopIteration
55+
}
4856
return gosdk.ResponseHeadersStatusContinue
4957
}
5058

5159
// ResponseBody implements [gosdk.HttpFilter].
52-
func (p headerAuthFilter) ResponseBody(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.ResponseBodyStatus {
60+
func (p *headerAuthFilter) ResponseBody(e gosdk.EnvoyHttpFilter, endOfStream bool) gosdk.ResponseBodyStatus {
5361
return gosdk.ResponseBodyStatusContinue
5462
}

integration/main_test.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,10 @@ func TestIntegration(t *testing.T) {
195195
return true
196196
}, 30*time.Second, 200*time.Millisecond)
197197

198-
got200 := false
199-
got403 := false
200198
require.Eventually(t, func() bool {
201199
req, err := http.NewRequest("GET", "http://localhost:1063/uuid", nil)
202200
require.NoError(t, err)
203-
req.Header.Add(gomoduleAuthHeader, "anything")
201+
req.Header.Add(gomoduleAuthHeader, "on_response_headers")
204202
resp, err := http.DefaultClient.Do(req)
205203
if err != nil {
206204
t.Logf("Envoy not ready yet: %v", err)
@@ -210,10 +208,27 @@ func TestIntegration(t *testing.T) {
210208
require.NoError(t, resp.Body.Close())
211209
}()
212210
body, err := io.ReadAll(resp.Body)
211+
require.NoError(t, err)
212+
t.Logf("response: status=%d body=%s", resp.StatusCode, string(body))
213+
return resp.StatusCode == 401
214+
}, 30*time.Second, 200*time.Millisecond)
215+
216+
got200 := false
217+
got403 := false
218+
require.Eventually(t, func() bool {
219+
req, err := http.NewRequest("GET", "http://localhost:1063/uuid", nil)
220+
require.NoError(t, err)
221+
req.Header.Add(gomoduleAuthHeader, "anything")
222+
resp, err := http.DefaultClient.Do(req)
213223
if err != nil {
214224
t.Logf("Envoy not ready yet: %v", err)
215225
return false
216226
}
227+
defer func() {
228+
require.NoError(t, resp.Body.Close())
229+
}()
230+
body, err := io.ReadAll(resp.Body)
231+
require.NoError(t, err)
217232
t.Logf("response: status=%d body=%s", resp.StatusCode, string(body))
218233
if resp.StatusCode == 200 {
219234
got200 = true

0 commit comments

Comments
 (0)