Move all HTTP error handling into error handling middleware
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Elara 2023-06-26 19:43:27 -07:00
parent d90da5dcf9
commit 6272e5e044

View File

@ -223,7 +223,7 @@ func registerWebhook(mux *http.ServeMux, cfg *config.Config, pluginName string)
} }
func webhookHandler(pluginName string, secure bool, cfg *config.Config, thread *starlark.Thread, fn *starlark.Function) http.HandlerFunc { func webhookHandler(pluginName string, secure bool, cfg *config.Config, thread *starlark.Thread, fn *starlark.Function) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return handleError(func(res http.ResponseWriter, req *http.Request) *HTTPError {
defer req.Body.Close() defer req.Body.Close()
res.Header().Add("X-Updater-Plugin", pluginName) res.Header().Add("X-Updater-Plugin", pluginName)
@ -231,20 +231,22 @@ func webhookHandler(pluginName string, secure bool, cfg *config.Config, thread *
if secure { if secure {
err := verifySecure(cfg.Webhook.PasswordHash, pluginName, req) err := verifySecure(cfg.Webhook.PasswordHash, pluginName, req)
if err != nil { if err != nil {
log.Error("Error verifying webhook").Err(err).Send() return &HTTPError{
res.WriteHeader(http.StatusForbidden) Message: "Error verifying webhook",
_, _ = io.WriteString(res, err.Error()) Code: http.StatusForbidden,
return Err: err,
}
} }
} }
log.Debug("Calling webhook function").Str("name", fn.Name()).Stringer("pos", fn.Position()).Send() log.Debug("Calling webhook function").Str("name", fn.Name()).Stringer("pos", fn.Position()).Send()
val, err := starlark.Call(thread, fn, starlark.Tuple{starlarkRequest(req)}, nil) val, err := starlark.Call(thread, fn, starlark.Tuple{starlarkRequest(req)}, nil)
if err != nil { if err != nil {
log.Error("Error while executing webhook").Err(err).Stringer("pos", fn.Position()).Send() return &HTTPError{
res.WriteHeader(http.StatusInternalServerError) Message: "Error while executing webhook",
_, _ = io.WriteString(res, err.Error()) Code: http.StatusInternalServerError,
return Err: err,
}
} }
switch val := val.(type) { switch val := val.(type) {
@ -262,13 +264,20 @@ func webhookHandler(pluginName string, secure bool, cfg *config.Config, thread *
body := newBodyReader() body := newBodyReader()
err = body.Unpack(val) err = body.Unpack(val)
if err != nil { if err != nil {
log.Error("Error unpacking returned body").Err(err).Send() return &HTTPError{
return Message: "Error unpacking returned body",
Code: http.StatusInternalServerError,
Err: err,
}
} }
_, err = io.Copy(res, body) _, err = io.Copy(res, body)
if err != nil { if err != nil {
log.Error("Error writing body").Err(err).Send() log.Error("Error writing body").Err(err).Send()
return return &HTTPError{
Message: "Error writing body",
Code: http.StatusInternalServerError,
Err: err,
}
} }
case *starlark.Dict: case *starlark.Dict:
code := http.StatusOK code := http.StatusOK
@ -276,8 +285,11 @@ func webhookHandler(pluginName string, secure bool, cfg *config.Config, thread *
if ok { if ok {
err = starlark.AsInt(codeVal, &code) err = starlark.AsInt(codeVal, &code)
if err != nil { if err != nil {
log.Error("Error decoding returned status code").Err(err).Send() return &HTTPError{
return Message: "Error decoding returned status code",
Code: http.StatusInternalServerError,
Err: err,
}
} }
res.WriteHeader(code) res.WriteHeader(code)
} }
@ -287,16 +299,40 @@ func webhookHandler(pluginName string, secure bool, cfg *config.Config, thread *
if ok { if ok {
err = body.Unpack(bodyVal) err = body.Unpack(bodyVal)
if err != nil { if err != nil {
log.Error("Error unpacking returned body").Err(err).Send() return &HTTPError{
return Message: "Error unpacking returned body",
Code: http.StatusInternalServerError,
Err: err,
}
} }
_, err = io.Copy(res, body) _, err = io.Copy(res, body)
if err != nil { if err != nil {
log.Error("Error writing body").Err(err).Send() return &HTTPError{
return Message: "Error writing body",
Code: http.StatusInternalServerError,
Err: err,
}
} }
} }
} }
return nil
})
}
type HTTPError struct {
Code int
Message string
Err error
}
func handleError(h func(res http.ResponseWriter, req *http.Request) *HTTPError) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) {
httpErr := h(res, req)
if httpErr != nil {
log.Error(httpErr.Message).Err(httpErr.Err).Send()
res.WriteHeader(httpErr.Code)
fmt.Sprintf("%s: %s", httpErr.Message, httpErr.Err)
}
} }
} }