From 819f6f627eb1c68d8b7ec8b4f071dfa7c3842af2 Mon Sep 17 00:00:00 2001 From: danicc097 Date: Sun, 19 Jan 2025 13:17:57 +0100 Subject: [PATCH] handler panic for rendering --- bin/templates/crud-api.go.tmpl.bash | 8 - .../oapi-templates/strict/strict-gin.tmpl | 10 + internal/rest/api_activity.go | 8 - internal/rest/api_notifications.go | 2 - internal/rest/api_oidc.go | 3 - internal/rest/api_team.go | 8 - internal/rest/api_user.go | 14 - internal/rest/api_work_item.go | 12 - internal/rest/api_work_item_comment.go | 8 - internal/rest/api_work_item_tag.go | 2 - internal/rest/middleware.auth.go | 12 +- internal/rest/middleware.db.go | 2 +- internal/rest/middleware.openapi.go | 6 +- internal/rest/openapi_server.gen.go | 470 ++++++++++++++++++ internal/rest/responses.go | 33 +- 15 files changed, 522 insertions(+), 76 deletions(-) diff --git a/bin/templates/crud-api.go.tmpl.bash b/bin/templates/crud-api.go.tmpl.bash index f257485f5..21286a828 100644 --- a/bin/templates/crud-api.go.tmpl.bash +++ b/bin/templates/crud-api.go.tmpl.bash @@ -18,8 +18,6 @@ $(test -n "$with_project" && echo " params.ProjectID = internal.ProjectIDByName[ ${camel_name}, err := h.svc.${pascal_name}.Create(c, tx, ¶ms) if err != nil { renderErrorResponse(c, "Could not create ${sentence_name}", err) - - return nil, nil } res := ${pascal_name}Response{ @@ -36,8 +34,6 @@ func (h *StrictHandlers) Get${pascal_name}(c *gin.Context, request Get${pascal_n ${camel_name}, err := h.svc.${pascal_name}.ByID(c, tx, request.${pascal_name}ID) if err != nil { renderErrorResponse(c, "Could not create ${sentence_name}", err) - - return nil, nil } res := ${pascal_name}Response{ @@ -56,8 +52,6 @@ func (h *StrictHandlers) Update${pascal_name}(c *gin.Context, request Update${pa ${camel_name}, err := h.svc.${pascal_name}.Update(c, tx, request.${pascal_name}ID, ¶ms) if err != nil { renderErrorResponse(c, "Could not update ${sentence_name}", err) - - return nil, nil } res := ${pascal_name}Response{ @@ -74,8 +68,6 @@ func (h *StrictHandlers) Delete${pascal_name}(c *gin.Context, request Delete${pa _, err := h.svc.${pascal_name}.Delete(c, tx, request.${pascal_name}ID) if err != nil { renderErrorResponse(c, "Could not delete ${sentence_name}", err) - - return nil, nil } return Delete${pascal_name}204Response{}, nil diff --git a/cmd/oapi-codegen/oapi-templates/strict/strict-gin.tmpl b/cmd/oapi-codegen/oapi-templates/strict/strict-gin.tmpl index b33028d51..7bce2314f 100644 --- a/cmd/oapi-codegen/oapi-templates/strict/strict-gin.tmpl +++ b/cmd/oapi-codegen/oapi-templates/strict/strict-gin.tmpl @@ -22,6 +22,16 @@ func (sh *strictHandlers) authMiddlewares(opID OperationID) []gin.HandlerFunc { {{$opid := .OperationId}} // {{$opid}} operation middleware func (sh *strictHandlers) {{.OperationId}}(ctx *gin.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params externalRef0.{{.OperationId}}Params{{end}}) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request {{$opid | ucFirst}}RequestObject {{range .PathParams -}} diff --git a/internal/rest/api_activity.go b/internal/rest/api_activity.go index f2af1af1a..3a92331d3 100644 --- a/internal/rest/api_activity.go +++ b/internal/rest/api_activity.go @@ -8,8 +8,6 @@ func (h *StrictHandlers) CreateActivity(c *gin.Context, request CreateActivityRe activity, err := h.svc.Activity.Create(c.Request.Context(), h.pool, request.ProjectName, &request.Body.ActivityCreateParams) if err != nil { renderErrorResponse(c, "could not create activity", err) - - return nil, nil } return CreateActivity201JSONResponse{Activity: *activity}, nil @@ -18,8 +16,6 @@ func (h *StrictHandlers) CreateActivity(c *gin.Context, request CreateActivityRe func (h *StrictHandlers) DeleteActivity(c *gin.Context, request DeleteActivityRequestObject) (DeleteActivityResponseObject, error) { if _, err := h.svc.Activity.Delete(c.Request.Context(), h.pool, request.ActivityID); err != nil { renderErrorResponse(c, "could not delete activity", err) - - return nil, nil } return DeleteActivity204Response{}, nil @@ -29,8 +25,6 @@ func (h *StrictHandlers) GetActivity(c *gin.Context, request GetActivityRequestO activity, err := h.svc.Activity.ByID(c.Request.Context(), h.pool, request.ActivityID) if err != nil { renderErrorResponse(c, "could not get activity", err) - - return nil, nil } return GetActivity200JSONResponse{Activity: *activity}, nil @@ -40,8 +34,6 @@ func (h *StrictHandlers) UpdateActivity(c *gin.Context, request UpdateActivityRe activity, err := h.svc.Activity.Update(c.Request.Context(), h.pool, request.ActivityID, &request.Body.ActivityUpdateParams) if err != nil { renderErrorResponse(c, "could not update activity", err) - - return nil, nil } return UpdateActivity200JSONResponse{Activity: *activity}, nil diff --git a/internal/rest/api_notifications.go b/internal/rest/api_notifications.go index 4af2e568f..79084901c 100644 --- a/internal/rest/api_notifications.go +++ b/internal/rest/api_notifications.go @@ -12,8 +12,6 @@ func (h *StrictHandlers) GetPaginatedNotifications(c *gin.Context, request GetPa nn, err := h.svc.Notification.PaginatedUserNotifications(c.Request.Context(), h.pool, caller.UserID, request.Params) if err != nil { renderErrorResponse(c, "Could not fetch notifications", err) - - return nil, nil } nextCursor := "" diff --git a/internal/rest/api_oidc.go b/internal/rest/api_oidc.go index 0cdde87c1..9559e09de 100644 --- a/internal/rest/api_oidc.go +++ b/internal/rest/api_oidc.go @@ -53,7 +53,6 @@ func (h *StrictHandlers) MyProviderCallback(c *gin.Context, request MyProviderCa userinfo, err := GetUserInfoFromCtx(c) if err != nil { renderErrorResponse(c, "OIDC authentication error", internal.WrapErrorf(err, models.ErrorCodeOIDC, "user info not found")) - return nil, nil } ctx := c.Request.Context() @@ -61,13 +60,11 @@ func (h *StrictHandlers) MyProviderCallback(c *gin.Context, request MyProviderCa u, err := h.svc.Authentication.GetOrRegisterUserFromUserInfo(ctx, *userinfo) if err != nil { renderErrorResponse(c, "OIDC authentication error", internal.WrapErrorf(err, models.ErrorCodeOIDC, "could not get or register user")) - return nil, nil } accessToken, err := h.svc.Authentication.CreateAccessTokenForUser(ctx, u) if err != nil { renderErrorResponse(c, "OIDC authentication error", internal.WrapErrorf(err, models.ErrorCodeOIDC, "could not create access token")) - return nil, nil } http.SetCookie(c.Writer, &http.Cookie{ diff --git a/internal/rest/api_team.go b/internal/rest/api_team.go index e7b38aeca..e02cc9377 100644 --- a/internal/rest/api_team.go +++ b/internal/rest/api_team.go @@ -18,8 +18,6 @@ func (h *StrictHandlers) CreateTeam(c *gin.Context, request CreateTeamRequestObj team, err := h.svc.Team.Create(ctx, tx, ¶ms) if err != nil { renderErrorResponse(c, "Could not create team", err) - - return nil, nil } h.event.Queue(ctx, fmt.Sprintf("team created: %v", team.TeamID), models.TopicTeamCreated) @@ -36,8 +34,6 @@ func (h *StrictHandlers) UpdateTeam(c *gin.Context, request UpdateTeamRequestObj team, err := h.svc.Team.Update(ctx, tx, models.TeamID(request.TeamID), ¶ms) if err != nil { renderErrorResponse(c, "Could not update team", err) - - return nil, nil } return UpdateTeam200JSONResponse{Team: *team}, nil @@ -50,8 +46,6 @@ func (h *StrictHandlers) GetTeam(c *gin.Context, request GetTeamRequestObject) ( team, err := h.svc.Team.ByID(ctx, tx, models.TeamID(request.TeamID)) if err != nil { renderErrorResponse(c, "Could not get team", err) - - return nil, nil } return GetTeam200JSONResponse{Team: *team}, nil @@ -64,8 +58,6 @@ func (h *StrictHandlers) DeleteTeam(c *gin.Context, request DeleteTeamRequestObj _, err := h.svc.Team.Delete(ctx, tx, models.TeamID(request.TeamID)) if err != nil { renderErrorResponse(c, "Could not delete team", err) - - return nil, nil } return DeleteTeam204Response{}, nil diff --git a/internal/rest/api_user.go b/internal/rest/api_user.go index 2fe3ba622..13653e36b 100644 --- a/internal/rest/api_user.go +++ b/internal/rest/api_user.go @@ -21,15 +21,11 @@ func (h *StrictHandlers) UpdateUser(c *gin.Context, request UpdateUserRequestObj user, err := h.svc.User.Update(c, tx, models.UserID{UUID: request.Id}, caller, request.Body) if err != nil { renderErrorResponse(c, "Could not update user", err) - - return nil, nil } role, ok := h.svc.Authorization.RoleByRank(user.RoleRank) if !ok { renderErrorResponse(c, fmt.Sprintf("Role with rank %d not found", user.RoleRank), nil) - - return nil, nil } res := UserResponse{User: user, Role: role.Name} @@ -43,8 +39,6 @@ func (h *StrictHandlers) DeleteUser(c *gin.Context, request DeleteUserRequestObj _, err := h.svc.User.Delete(c, tx, models.NewUserID(request.Id)) if err != nil { renderErrorResponse(c, "Could not delete user", err) - - return nil, nil } return DeleteUser204Response{}, nil @@ -57,8 +51,6 @@ func (h *StrictHandlers) GetCurrentUser(c *gin.Context, request GetCurrentUserRe if !ok { msg := fmt.Sprintf("role with rank %d not found", caller.RoleRank) renderErrorResponse(c, msg, errors.New(msg)) - - return nil, nil } res := UserResponse{ @@ -82,8 +74,6 @@ func (h *StrictHandlers) UpdateUserAuthorization(c *gin.Context, request UpdateU if _, err := h.svc.User.UpdateUserAuthorization(c, tx, models.UserID{UUID: request.Id}, caller, request.Body); err != nil { renderErrorResponse(c, "Error updating user authorization", err) - - return nil, nil } return UpdateUserAuthorization204Response{}, nil @@ -93,8 +83,6 @@ func (h *StrictHandlers) GetPaginatedUsers(c *gin.Context, request GetPaginatedU users, err := h.svc.User.Paginated(c, h.pool, request.Params) if err != nil { renderErrorResponse(c, "Could not update user", err) - - return nil, nil } nextCursor := "" @@ -103,8 +91,6 @@ func (h *StrictHandlers) GetPaginatedUsers(c *gin.Context, request GetPaginatedU nextCursor, err = getNextCursor(lastUser, request.Params.Column, models.TableEntityUser) if err != nil { renderErrorResponse(c, "Could not define next cursor", err) - - return nil, nil } } items := make([]UserResponse, len(users)) diff --git a/internal/rest/api_work_item.go b/internal/rest/api_work_item.go index e776b9755..06e2c62c7 100644 --- a/internal/rest/api_work_item.go +++ b/internal/rest/api_work_item.go @@ -37,8 +37,6 @@ func (h *StrictHandlers) CreateWorkitem(c *gin.Context, request CreateWorkitemRe jsonBody, err := io.ReadAll(c.Request.Body) if err != nil { renderErrorResponse(c, "Failed to read request body", err) - - return nil, nil } span.SetAttributes(tracing.MetadataAttribute(jsonBody)) c.Request.Body = io.NopCloser(bytes.NewBuffer(jsonBody)) @@ -46,16 +44,12 @@ func (h *StrictHandlers) CreateWorkitem(c *gin.Context, request CreateWorkitemRe project, err := projectByDiscriminator(request.Body) if err != nil { renderErrorResponse(c, "Failed to get project", err) - - return nil, nil } var res any // depends on project b, err := request.Body.ValueByDiscriminator() if err != nil { renderErrorResponse(c, "Failed to read discriminator", err) - - return nil, nil } //exhaustive:enforce @@ -74,8 +68,6 @@ func (h *StrictHandlers) CreateWorkitem(c *gin.Context, request CreateWorkitemRe }) if err != nil { renderErrorResponse(c, "Could not create work item", err) - - return nil, nil } res = DemoWorkItemResponse{ @@ -96,8 +88,6 @@ func (h *StrictHandlers) CreateWorkitem(c *gin.Context, request CreateWorkitemRe }) if err != nil { renderErrorResponse(c, "Could not create work item", err) - - return nil, nil } res = DemoTwoWorkItemResponse{ @@ -106,8 +96,6 @@ func (h *StrictHandlers) CreateWorkitem(c *gin.Context, request CreateWorkitemRe } default: renderErrorResponse(c, "Unknown discriminator", internal.NewErrorf(models.ErrorCodeUnknown, "%+v", b)) - - return nil, nil } var resJson *CreateWorkitem201JSONResponse diff --git a/internal/rest/api_work_item_comment.go b/internal/rest/api_work_item_comment.go index 2619021e1..ddf0d40fb 100644 --- a/internal/rest/api_work_item_comment.go +++ b/internal/rest/api_work_item_comment.go @@ -13,8 +13,6 @@ func (h *StrictHandlers) CreateWorkItemComment(c *gin.Context, request CreateWor workItemComment, err := h.svc.WorkItemComment.Create(c, tx, ¶ms) if err != nil { renderErrorResponse(c, "Could not create work item comment", err) - - return nil, nil } res := WorkItemCommentResponse{ @@ -31,8 +29,6 @@ func (h *StrictHandlers) GetWorkItemComment(c *gin.Context, request GetWorkItemC workItemComment, err := h.svc.WorkItemComment.ByID(c, tx, request.WorkItemCommentID) if err != nil { renderErrorResponse(c, "Could not create work item comment", err) - - return nil, nil } res := WorkItemCommentResponse{ @@ -52,8 +48,6 @@ func (h *StrictHandlers) UpdateWorkItemComment(c *gin.Context, request UpdateWor workItemComment, err := h.svc.WorkItemComment.Update(c, tx, caller, models.WorkItemCommentID(request.WorkItemCommentID), ¶ms) if err != nil { renderErrorResponse(c, "Could not update work item comment", err) - - return nil, nil } res := WorkItemCommentResponse{ @@ -71,8 +65,6 @@ func (h *StrictHandlers) DeleteWorkItemComment(c *gin.Context, request DeleteWor _, err := h.svc.WorkItemComment.Delete(c, tx, caller, models.WorkItemCommentID(request.WorkItemCommentID)) if err != nil { renderErrorResponse(c, "Could not delete work item comment", err) - - return nil, nil } return DeleteWorkItemComment204Response{}, nil diff --git a/internal/rest/api_work_item_tag.go b/internal/rest/api_work_item_tag.go index b69b509e6..28e3caa02 100644 --- a/internal/rest/api_work_item_tag.go +++ b/internal/rest/api_work_item_tag.go @@ -18,8 +18,6 @@ func (h *StrictHandlers) CreateWorkItemTag(c *gin.Context, request CreateWorkIte wit, err := h.svc.WorkItemTag.Create(ctx, tx, caller, &body.WorkItemTagCreateParams) if err != nil { renderErrorResponse(c, "Could not create work item tag", err) - - return nil, nil } return CreateWorkItemTag201JSONResponse{WorkItemTag: *wit}, nil diff --git a/internal/rest/middleware.auth.go b/internal/rest/middleware.auth.go index b2fcc33c6..e9ab2c800 100644 --- a/internal/rest/middleware.auth.go +++ b/internal/rest/middleware.auth.go @@ -45,7 +45,7 @@ func (m *authMiddleware) EnsureAuthenticated() gin.HandlerFunc { if apiKey != "" { u, err := m.svc.Authentication.GetUserFromAPIKey(c.Request.Context(), apiKey) // includes caller joins if err != nil || u == nil { - renderErrorResponse(c, "Unauthenticated", internal.NewErrorf(models.ErrorCodeUnauthenticated, "could not get user from api key")) + renderErrorResponse(c, "Unauthenticated", internal.NewErrorf(models.ErrorCodeUnauthenticated, "could not get user from api key"), WithoutPanic()) c.Abort() return @@ -60,7 +60,7 @@ func (m *authMiddleware) EnsureAuthenticated() gin.HandlerFunc { if strings.HasPrefix(auth, "Bearer ") { u, err := m.svc.Authentication.GetUserFromAccessToken(c.Request.Context(), strings.Split(auth, "Bearer ")[1]) // includes caller joins if err != nil || u == nil { - renderErrorResponse(c, "Unauthenticated", internal.NewErrorf(models.ErrorCodeUnauthenticated, "could not get user from token: %s", err)) + renderErrorResponse(c, "Unauthenticated", internal.NewErrorf(models.ErrorCodeUnauthenticated, "could not get user from token: %s", err), WithoutPanic()) c.Abort() return @@ -73,7 +73,7 @@ func (m *authMiddleware) EnsureAuthenticated() gin.HandlerFunc { return } - renderErrorResponse(c, "Unauthenticated", internal.NewErrorf(models.ErrorCodeUnauthenticated, "could not get user from token")) + renderErrorResponse(c, "Unauthenticated", internal.NewErrorf(models.ErrorCodeUnauthenticated, "could not get user from token"), WithoutPanic()) c.Abort() } } @@ -91,7 +91,7 @@ func (m *authMiddleware) EnsureAuthorized(config AuthRestriction) gin.HandlerFun errs := []string{} user, err := GetUserCallerFromCtx(c) if err != nil { - renderErrorResponse(c, "Could not get current user.", nil) + renderErrorResponse(c, "Could not get current user.", nil, WithoutPanic()) c.Abort() return @@ -100,7 +100,7 @@ func (m *authMiddleware) EnsureAuthorized(config AuthRestriction) gin.HandlerFun if config.MinimumRole != "" { userRole, ok := m.svc.Authorization.RoleByRank(user.RoleRank) if !ok { - renderErrorResponse(c, fmt.Sprintf("Unknown rank value: %d", user.RoleRank), errors.New("unknown rank")) + renderErrorResponse(c, fmt.Sprintf("Unknown rank value: %d", user.RoleRank), errors.New("unknown rank"), WithoutPanic()) c.Abort() return @@ -129,7 +129,7 @@ func (m *authMiddleware) EnsureAuthorized(config AuthRestriction) gin.HandlerFun errorMsg = fmt.Sprintf("either %s are required", slices.Join(errs, " or ")) } - renderErrorResponse(c, "Unauthorized", internal.NewErrorf(models.ErrorCodeUnauthorized, "unauthorized: "+errorMsg)) + renderErrorResponse(c, "Unauthorized", internal.NewErrorf(models.ErrorCodeUnauthorized, "unauthorized: "+errorMsg), WithoutPanic()) c.Abort() } } diff --git a/internal/rest/middleware.db.go b/internal/rest/middleware.db.go index 201e5f401..1b3fddcad 100644 --- a/internal/rest/middleware.db.go +++ b/internal/rest/middleware.db.go @@ -32,7 +32,7 @@ func (m *dbMiddleware) BeginTransaction() gin.HandlerFunc { tx, err := m.pool.BeginTx(ctx, pgx.TxOptions{}) if err != nil { - renderErrorResponse(c, "", internal.WrapErrorf(err, models.ErrorCodePrivate, "could not begin transaction")) + renderErrorResponse(c, "", internal.WrapErrorf(err, models.ErrorCodePrivate, "could not begin transaction"), WithoutPanic()) c.Abort() return diff --git a/internal/rest/middleware.openapi.go b/internal/rest/middleware.openapi.go index a767320d6..8fd2d0a10 100644 --- a/internal/rest/middleware.openapi.go +++ b/internal/rest/middleware.openapi.go @@ -82,7 +82,7 @@ func (m *openapiMiddleware) RequestValidatorWithOptions(options *OAValidatorOpti options.ErrorHandler(c, err.Error(), http.StatusBadRequest) } else { // error response customized via WithCustomSchemaErrorFunc - renderErrorResponse(c, "Invalid request", internal.WrapErrorf(err, models.ErrorCodeRequestValidation, "OpenAPI request validation failed")) + renderErrorResponse(c, "Invalid request", internal.WrapErrorf(err, models.ErrorCodeRequestValidation, "OpenAPI request validation failed"), WithoutPanic()) } rbw.ResponseWriter.Write(rbw.body.Bytes()) @@ -102,7 +102,7 @@ func (m *openapiMiddleware) RequestValidatorWithOptions(options *OAValidatorOpti rvi, err := buildRequestValidationInput(m.router, c.Request, &options.Options) if err != nil { // error response customized via WithCustomSchemaErrorFunc - renderErrorResponse(c, fmt.Sprintf("openapi request validation input: %v", err), err) + renderErrorResponse(c, fmt.Sprintf("openapi request validation input: %v", err), err, WithoutPanic()) rbw.ResponseWriter.Write(rbw.body.Bytes()) return @@ -120,7 +120,7 @@ func (m *openapiMiddleware) RequestValidatorWithOptions(options *OAValidatorOpti if err := openapi3filter.ValidateResponse(c.Request.Context(), input); err != nil { rbw.body.Reset() - renderErrorResponse(c, "Invalid response", internal.WrapErrorf(err, models.ErrorCodeResponseValidation, "OpenAPI response validation failed")) + renderErrorResponse(c, "Invalid response", internal.WrapErrorf(err, models.ErrorCodeResponseValidation, "OpenAPI response validation failed"), WithoutPanic()) rbw.ResponseWriter.Write(rbw.body.Bytes()) return diff --git a/internal/rest/openapi_server.gen.go b/internal/rest/openapi_server.gen.go index f08fa1fa6..7c1c70df9 100644 --- a/internal/rest/openapi_server.gen.go +++ b/internal/rest/openapi_server.gen.go @@ -3318,6 +3318,16 @@ func (sh *strictHandlers) authMiddlewares(opID OperationID) []gin.HandlerFunc { // DeleteActivity operation middleware func (sh *strictHandlers) DeleteActivity(ctx *gin.Context, activityID models.ActivityID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteActivityRequestObject request.ActivityID = activityID @@ -3345,6 +3355,16 @@ func (sh *strictHandlers) DeleteActivity(ctx *gin.Context, activityID models.Act // GetActivity operation middleware func (sh *strictHandlers) GetActivity(ctx *gin.Context, activityID models.ActivityID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetActivityRequestObject request.ActivityID = activityID @@ -3372,6 +3392,16 @@ func (sh *strictHandlers) GetActivity(ctx *gin.Context, activityID models.Activi // UpdateActivity operation middleware func (sh *strictHandlers) UpdateActivity(ctx *gin.Context, activityID models.ActivityID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateActivityRequestObject request.ActivityID = activityID @@ -3408,6 +3438,16 @@ func (sh *strictHandlers) UpdateActivity(ctx *gin.Context, activityID models.Act // AdminPing operation middleware func (sh *strictHandlers) AdminPing(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request AdminPingRequestObject handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { @@ -3433,6 +3473,16 @@ func (sh *strictHandlers) AdminPing(ctx *gin.Context) { // MyProviderCallback operation middleware func (sh *strictHandlers) MyProviderCallback(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request MyProviderCallbackRequestObject handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { @@ -3458,6 +3508,16 @@ func (sh *strictHandlers) MyProviderCallback(ctx *gin.Context) { // MyProviderLogin operation middleware func (sh *strictHandlers) MyProviderLogin(ctx *gin.Context, params externalRef0.MyProviderLoginParams) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request MyProviderLoginRequestObject request.Params = params @@ -3485,6 +3545,16 @@ func (sh *strictHandlers) MyProviderLogin(ctx *gin.Context, params externalRef0. // Events operation middleware func (sh *strictHandlers) Events(ctx *gin.Context, params externalRef0.EventsParams) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request EventsRequestObject request.Params = params @@ -3512,6 +3582,16 @@ func (sh *strictHandlers) Events(ctx *gin.Context, params externalRef0.EventsPar // GetPaginatedNotifications operation middleware func (sh *strictHandlers) GetPaginatedNotifications(ctx *gin.Context, params externalRef0.GetPaginatedNotificationsParams) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetPaginatedNotificationsRequestObject request.Params = params @@ -3539,6 +3619,16 @@ func (sh *strictHandlers) GetPaginatedNotifications(ctx *gin.Context, params ext // OpenapiYamlGet operation middleware func (sh *strictHandlers) OpenapiYamlGet(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request OpenapiYamlGetRequestObject handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { @@ -3564,6 +3654,16 @@ func (sh *strictHandlers) OpenapiYamlGet(ctx *gin.Context) { // Ping operation middleware func (sh *strictHandlers) Ping(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request PingRequestObject handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { @@ -3589,6 +3689,16 @@ func (sh *strictHandlers) Ping(ctx *gin.Context) { // GetProject operation middleware func (sh *strictHandlers) GetProject(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetProjectRequestObject request.ProjectName = projectName @@ -3616,6 +3726,16 @@ func (sh *strictHandlers) GetProject(ctx *gin.Context, projectName externalRef0. // CreateActivity operation middleware func (sh *strictHandlers) CreateActivity(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateActivityRequestObject request.ProjectName = projectName @@ -3652,6 +3772,16 @@ func (sh *strictHandlers) CreateActivity(ctx *gin.Context, projectName externalR // GetProjectBoard operation middleware func (sh *strictHandlers) GetProjectBoard(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetProjectBoardRequestObject request.ProjectName = projectName @@ -3679,6 +3809,16 @@ func (sh *strictHandlers) GetProjectBoard(ctx *gin.Context, projectName external // GetProjectConfig operation middleware func (sh *strictHandlers) GetProjectConfig(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetProjectConfigRequestObject request.ProjectName = projectName @@ -3706,6 +3846,16 @@ func (sh *strictHandlers) GetProjectConfig(ctx *gin.Context, projectName externa // UpdateProjectConfig operation middleware func (sh *strictHandlers) UpdateProjectConfig(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateProjectConfigRequestObject request.ProjectName = projectName @@ -3742,6 +3892,16 @@ func (sh *strictHandlers) UpdateProjectConfig(ctx *gin.Context, projectName exte // InitializeProject operation middleware func (sh *strictHandlers) InitializeProject(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request InitializeProjectRequestObject request.ProjectName = projectName @@ -3778,6 +3938,16 @@ func (sh *strictHandlers) InitializeProject(ctx *gin.Context, projectName extern // CreateTeam operation middleware func (sh *strictHandlers) CreateTeam(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateTeamRequestObject request.ProjectName = projectName @@ -3814,6 +3984,16 @@ func (sh *strictHandlers) CreateTeam(ctx *gin.Context, projectName externalRef0. // CreateWorkItemTag operation middleware func (sh *strictHandlers) CreateWorkItemTag(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateWorkItemTagRequestObject request.ProjectName = projectName @@ -3850,6 +4030,16 @@ func (sh *strictHandlers) CreateWorkItemTag(ctx *gin.Context, projectName extern // CreateWorkItemType operation middleware func (sh *strictHandlers) CreateWorkItemType(ctx *gin.Context, projectName externalRef0.ProjectName) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateWorkItemTypeRequestObject request.ProjectName = projectName @@ -3886,6 +4076,16 @@ func (sh *strictHandlers) CreateWorkItemType(ctx *gin.Context, projectName exter // GetProjectWorkitems operation middleware func (sh *strictHandlers) GetProjectWorkitems(ctx *gin.Context, projectName externalRef0.ProjectName, params externalRef0.GetProjectWorkitemsParams) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetProjectWorkitemsRequestObject request.ProjectName = projectName @@ -3914,6 +4114,16 @@ func (sh *strictHandlers) GetProjectWorkitems(ctx *gin.Context, projectName exte // DeleteTeam operation middleware func (sh *strictHandlers) DeleteTeam(ctx *gin.Context, teamID models.TeamID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteTeamRequestObject request.TeamID = teamID @@ -3941,6 +4151,16 @@ func (sh *strictHandlers) DeleteTeam(ctx *gin.Context, teamID models.TeamID) { // GetTeam operation middleware func (sh *strictHandlers) GetTeam(ctx *gin.Context, teamID models.TeamID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetTeamRequestObject request.TeamID = teamID @@ -3968,6 +4188,16 @@ func (sh *strictHandlers) GetTeam(ctx *gin.Context, teamID models.TeamID) { // UpdateTeam operation middleware func (sh *strictHandlers) UpdateTeam(ctx *gin.Context, teamID models.TeamID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateTeamRequestObject request.TeamID = teamID @@ -4004,6 +4234,16 @@ func (sh *strictHandlers) UpdateTeam(ctx *gin.Context, teamID models.TeamID) { // CreateTimeEntry operation middleware func (sh *strictHandlers) CreateTimeEntry(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateTimeEntryRequestObject // CreateTimeEntryRequest @@ -4038,6 +4278,16 @@ func (sh *strictHandlers) CreateTimeEntry(ctx *gin.Context) { // DeleteTimeEntry operation middleware func (sh *strictHandlers) DeleteTimeEntry(ctx *gin.Context, timeEntryID models.TimeEntryID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteTimeEntryRequestObject request.TimeEntryID = timeEntryID @@ -4065,6 +4315,16 @@ func (sh *strictHandlers) DeleteTimeEntry(ctx *gin.Context, timeEntryID models.T // GetTimeEntry operation middleware func (sh *strictHandlers) GetTimeEntry(ctx *gin.Context, timeEntryID models.TimeEntryID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetTimeEntryRequestObject request.TimeEntryID = timeEntryID @@ -4092,6 +4352,16 @@ func (sh *strictHandlers) GetTimeEntry(ctx *gin.Context, timeEntryID models.Time // UpdateTimeEntry operation middleware func (sh *strictHandlers) UpdateTimeEntry(ctx *gin.Context, timeEntryID models.TimeEntryID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateTimeEntryRequestObject request.TimeEntryID = timeEntryID @@ -4128,6 +4398,16 @@ func (sh *strictHandlers) UpdateTimeEntry(ctx *gin.Context, timeEntryID models.T // GetCurrentUser operation middleware func (sh *strictHandlers) GetCurrentUser(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetCurrentUserRequestObject handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { @@ -4153,6 +4433,16 @@ func (sh *strictHandlers) GetCurrentUser(ctx *gin.Context) { // GetPaginatedUsers operation middleware func (sh *strictHandlers) GetPaginatedUsers(ctx *gin.Context, params externalRef0.GetPaginatedUsersParams) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetPaginatedUsersRequestObject request.Params = params @@ -4180,6 +4470,16 @@ func (sh *strictHandlers) GetPaginatedUsers(ctx *gin.Context, params externalRef // DeleteUser operation middleware func (sh *strictHandlers) DeleteUser(ctx *gin.Context, id uuid.UUID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteUserRequestObject request.Id = id @@ -4207,6 +4507,16 @@ func (sh *strictHandlers) DeleteUser(ctx *gin.Context, id uuid.UUID) { // UpdateUser operation middleware func (sh *strictHandlers) UpdateUser(ctx *gin.Context, id uuid.UUID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateUserRequestObject request.Id = id @@ -4243,6 +4553,16 @@ func (sh *strictHandlers) UpdateUser(ctx *gin.Context, id uuid.UUID) { // UpdateUserAuthorization operation middleware func (sh *strictHandlers) UpdateUserAuthorization(ctx *gin.Context, id uuid.UUID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateUserAuthorizationRequestObject request.Id = id @@ -4279,6 +4599,16 @@ func (sh *strictHandlers) UpdateUserAuthorization(ctx *gin.Context, id uuid.UUID // DeleteWorkItemTag operation middleware func (sh *strictHandlers) DeleteWorkItemTag(ctx *gin.Context, workItemTagID models.WorkItemTagID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteWorkItemTagRequestObject request.WorkItemTagID = workItemTagID @@ -4306,6 +4636,16 @@ func (sh *strictHandlers) DeleteWorkItemTag(ctx *gin.Context, workItemTagID mode // GetWorkItemTag operation middleware func (sh *strictHandlers) GetWorkItemTag(ctx *gin.Context, workItemTagID models.WorkItemTagID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetWorkItemTagRequestObject request.WorkItemTagID = workItemTagID @@ -4333,6 +4673,16 @@ func (sh *strictHandlers) GetWorkItemTag(ctx *gin.Context, workItemTagID models. // UpdateWorkItemTag operation middleware func (sh *strictHandlers) UpdateWorkItemTag(ctx *gin.Context, workItemTagID models.WorkItemTagID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateWorkItemTagRequestObject request.WorkItemTagID = workItemTagID @@ -4369,6 +4719,16 @@ func (sh *strictHandlers) UpdateWorkItemTag(ctx *gin.Context, workItemTagID mode // DeleteWorkItemType operation middleware func (sh *strictHandlers) DeleteWorkItemType(ctx *gin.Context, workItemTypeID models.WorkItemTypeID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteWorkItemTypeRequestObject request.WorkItemTypeID = workItemTypeID @@ -4396,6 +4756,16 @@ func (sh *strictHandlers) DeleteWorkItemType(ctx *gin.Context, workItemTypeID mo // GetWorkItemType operation middleware func (sh *strictHandlers) GetWorkItemType(ctx *gin.Context, workItemTypeID models.WorkItemTypeID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetWorkItemTypeRequestObject request.WorkItemTypeID = workItemTypeID @@ -4423,6 +4793,16 @@ func (sh *strictHandlers) GetWorkItemType(ctx *gin.Context, workItemTypeID model // UpdateWorkItemType operation middleware func (sh *strictHandlers) UpdateWorkItemType(ctx *gin.Context, workItemTypeID models.WorkItemTypeID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateWorkItemTypeRequestObject request.WorkItemTypeID = workItemTypeID @@ -4459,6 +4839,16 @@ func (sh *strictHandlers) UpdateWorkItemType(ctx *gin.Context, workItemTypeID mo // CreateWorkitem operation middleware func (sh *strictHandlers) CreateWorkitem(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateWorkitemRequestObject // CreateWorkitemRequest @@ -4493,6 +4883,16 @@ func (sh *strictHandlers) CreateWorkitem(ctx *gin.Context) { // GetPaginatedWorkItem operation middleware func (sh *strictHandlers) GetPaginatedWorkItem(ctx *gin.Context, params externalRef0.GetPaginatedWorkItemParams) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetPaginatedWorkItemRequestObject request.Params = params @@ -4520,6 +4920,16 @@ func (sh *strictHandlers) GetPaginatedWorkItem(ctx *gin.Context, params external // DeleteWorkitem operation middleware func (sh *strictHandlers) DeleteWorkitem(ctx *gin.Context, workItemID models.WorkItemID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteWorkitemRequestObject request.WorkItemID = workItemID @@ -4547,6 +4957,16 @@ func (sh *strictHandlers) DeleteWorkitem(ctx *gin.Context, workItemID models.Wor // GetWorkItem operation middleware func (sh *strictHandlers) GetWorkItem(ctx *gin.Context, workItemID models.WorkItemID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetWorkItemRequestObject request.WorkItemID = workItemID @@ -4574,6 +4994,16 @@ func (sh *strictHandlers) GetWorkItem(ctx *gin.Context, workItemID models.WorkIt // UpdateWorkitem operation middleware func (sh *strictHandlers) UpdateWorkitem(ctx *gin.Context, workItemID models.WorkItemID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateWorkitemRequestObject request.WorkItemID = workItemID @@ -4601,6 +5031,16 @@ func (sh *strictHandlers) UpdateWorkitem(ctx *gin.Context, workItemID models.Wor // CreateWorkItemComment operation middleware func (sh *strictHandlers) CreateWorkItemComment(ctx *gin.Context, workItemID int) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request CreateWorkItemCommentRequestObject request.WorkItemID = workItemID @@ -4637,6 +5077,16 @@ func (sh *strictHandlers) CreateWorkItemComment(ctx *gin.Context, workItemID int // DeleteWorkItemComment operation middleware func (sh *strictHandlers) DeleteWorkItemComment(ctx *gin.Context, workItemID models.WorkItemID, workItemCommentID models.WorkItemCommentID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request DeleteWorkItemCommentRequestObject request.WorkItemID = workItemID @@ -4665,6 +5115,16 @@ func (sh *strictHandlers) DeleteWorkItemComment(ctx *gin.Context, workItemID mod // GetWorkItemComment operation middleware func (sh *strictHandlers) GetWorkItemComment(ctx *gin.Context, workItemID models.WorkItemID, workItemCommentID models.WorkItemCommentID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request GetWorkItemCommentRequestObject request.WorkItemID = workItemID @@ -4693,6 +5153,16 @@ func (sh *strictHandlers) GetWorkItemComment(ctx *gin.Context, workItemID models // UpdateWorkItemComment operation middleware func (sh *strictHandlers) UpdateWorkItemComment(ctx *gin.Context, workItemID models.WorkItemID, workItemCommentID models.WorkItemCommentID) { + defer func() { + if r := recover(); r != nil { + // handler() may panic to notify early handler exit + if _, ok := r.(*HandlerExitError); !ok { + panic(r) + } + // swallow panic, assume error response was rendered already to gin context + } + }() + var request UpdateWorkItemCommentRequestObject request.WorkItemID = workItemID diff --git a/internal/rest/responses.go b/internal/rest/responses.go index c8e16958b..4af5a39a2 100644 --- a/internal/rest/responses.go +++ b/internal/rest/responses.go @@ -17,10 +17,35 @@ import ( "go.opentelemetry.io/otel/trace" ) +// HandlerExitError is used to exit handlers early after rendering an error response. +type HandlerExitError struct{} + +func (e *HandlerExitError) Error() string { + return "handler exit requested" +} + +type RenderErrorOptions struct { + WithoutPanic bool +} + +type RenderErrorOption func(*RenderErrorOptions) + +// WithoutPanic prevents renderErrorResponse from panicking with a HandlerExitError. +func WithoutPanic() RenderErrorOption { + return func(o *RenderErrorOptions) { + o.WithoutPanic = true + } +} + // renderErrorResponse writes an error response from title and error. // title represents an error title which will be shown to end users. // Inspired by https://www.rfc-editor.org/rfc/rfc7807. -func renderErrorResponse(c *gin.Context, title string, err error) { +func renderErrorResponse(c *gin.Context, title string, err error, opts ...RenderErrorOption) { + options := RenderErrorOptions{} + for _, opt := range opts { + opt(&options) + } + if err == nil { err = errors.New("unknown error") } @@ -126,6 +151,12 @@ func renderErrorResponse(c *gin.Context, title string, err error) { CtxWithRequestError(c) renderResponse(c, resp, resp.Status) + + // will trigger handler exit only for convenience in handlers and their utility functions. + // it then recovers and executes subsequent middlewares. + if !options.WithoutPanic { + panic(&HandlerExitError{}) + } } func extractValidationError(err error) *models.HTTPValidationError {