diff --git a/githubapp/dispatcher.go b/githubapp/dispatcher.go index 9d5be8f9f..6d5719d9c 100644 --- a/githubapp/dispatcher.go +++ b/githubapp/dispatcher.go @@ -134,10 +134,7 @@ func (d *eventDispatcher) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // initialize context for SetResponder/GetResponder - // we store a pointer in the context so that functions deeper in the call - // tree can modify the value without creating a new context - var responder func(http.ResponseWriter, *http.Request) - ctx = context.WithValue(ctx, responderKey{}, &responder) + ctx = InitializeResponder(ctx) r = r.WithContext(ctx) eventType := r.Header.Get("X-GitHub-Event") @@ -216,9 +213,17 @@ func DefaultResponseCallback(w http.ResponseWriter, r *http.Request, event strin type responderKey struct{} +// InitializeResponder prepares the context to work with SetResponder and +// GetResponder. It is used to test handlers that call SetResponder or to +// implement custom event dispatchers that support responders. +func InitializeResponder(ctx context.Context) context.Context { + var responder func(http.ResponseWriter, *http.Request) + return context.WithValue(ctx, responderKey{}, &responder) +} + // SetResponder sets a function that sends a response to GitHub after event -// processing completes. This function may only be called from event handler -// functions invoked by the event dispatcher. +// processing completes. The context must be initialized by InitializeResponder. +// The event dispatcher does this automatically before calling a handler. // // Customizing individual handler responses should be rare. Applications that // want to modify the standard responses should consider registering a response @@ -226,7 +231,7 @@ type responderKey struct{} func SetResponder(ctx context.Context, responder func(http.ResponseWriter, *http.Request)) { r, ok := ctx.Value(responderKey{}).(*func(http.ResponseWriter, *http.Request)) if !ok || r == nil { - panic("SetResponder() must be called from an event handler invoked by the go-githubapp event dispatcher") + panic("SetResponder() must be called with an initialized context, such as one from the event dispatcher") } *r = responder }