Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Adding WithContextFunc for webhook server to pass info to the handler #1334

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion pkg/webhook/admission/http.go
Expand Up @@ -45,6 +45,10 @@ var _ http.Handler = &Webhook{}
func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var body []byte
var err error
ctx := r.Context()
if wh.WithContextFunc != nil {
ctx = wh.WithContextFunc(ctx, r)
}

var reviewResponse Response
if r.Body != nil {
Expand Down Expand Up @@ -93,7 +97,7 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
wh.log.V(1).Info("received request", "UID", req.UID, "kind", req.Kind, "resource", req.Resource)

// TODO: add panic-recovery for Handle
reviewResponse = wh.Handle(r.Context(), req)
reviewResponse = wh.Handle(ctx, req)
wh.writeResponseTyped(w, reviewResponse, actualAdmRevGVK)
}

Expand Down
28 changes: 28 additions & 0 deletions pkg/webhook/admission/http_test.go
Expand Up @@ -162,6 +162,34 @@ var _ = Describe("Admission Webhooks", func() {
webhook.ServeHTTP(respRecorder, req.WithContext(ctx))
Expect(respRecorder.Body.String()).To(Equal(expected))
})

It("should mutate the Context from the HTTP request, if func supplied", func() {
req := &http.Request{
Header: http.Header{"Content-Type": []string{"application/json"}},
Body: nopCloser{Reader: bytes.NewBufferString(`{"request":{}}`)},
}
type ctxkey int
const key ctxkey = 1
webhook := &Webhook{
Handler: &fakeHandler{
fn: func(ctx context.Context, req Request) Response {
return Allowed(ctx.Value(key).(string))
},
},
WithContextFunc: func(ctx context.Context, r *http.Request) context.Context {
return context.WithValue(ctx, key, r.Header["Content-Type"][0])
},
log: logf.RuntimeLog.WithName("webhook"),
}

expected := fmt.Sprintf(`{%s,"response":{"uid":"","allowed":true,"status":{"metadata":{},"reason":%q,"code":200}}}
`, gvkJSONv1, "application/json")

ctx, cancel := context.WithCancel(context.Background())
cancel()
webhook.ServeHTTP(respRecorder, req.WithContext(ctx))
Expect(respRecorder.Body.String()).To(Equal(expected))
})
})
})

Expand Down
5 changes: 5 additions & 0 deletions pkg/webhook/admission/webhook.go
Expand Up @@ -115,6 +115,11 @@ type Webhook struct {
// and potentially patches to apply to the handler.
Handler Handler

// WithContextFunc will allow you to take the http.Request.Context() and
// add any additional information such as passing the request path or
// headers thus allowing you to read them from within the handler
WithContextFunc func(context.Context, *http.Request) context.Context

// decoder is constructed on receiving a scheme and passed down to then handler
decoder *Decoder

Expand Down