diff --git a/problem_config.go b/problem_config.go index da92f53..087d4be 100644 --- a/problem_config.go +++ b/problem_config.go @@ -14,10 +14,14 @@ type ProblemConfig struct { func NewProblemConfig() ProblemConfig { return ProblemConfig{ ErrorTypePaths: map[string]string{ - "validation_error": "/errors/validation-error", - "not_found_error": "/errors/not-found", - "server_error": "/errors/server-error", - "bad_request_error": "/errors/bad-request", + "validation_error": "/errors/validation-error", + "not_found_error": "/errors/not-found", + "server_error": "/errors/server-error", + "bad_request_error": "/errors/bad-request", + "unauthorized_error": "/errors/unauthorized", + "forbidden_error": "/errors/forbidden", + "conflict_error": "/errors/conflict", + "unprocessable_error": "/errors/unprocessable-entity", }, } } diff --git a/problem_helpers.go b/problem_helpers.go index 7179fe9..b629440 100644 --- a/problem_helpers.go +++ b/problem_helpers.go @@ -18,6 +18,46 @@ func ProblemNotFound(detail string) *ProblemBuilder { Detail(detail) } +// ProblemUnauthorized returns an unauthorized problem builder. +func ProblemUnauthorized(detail string) *ProblemBuilder { + return Problem(http.StatusUnauthorized). + Type(GetProblemTypeURL("unauthorized_error")). + Title("Unauthorized"). + Detail(detail) +} + +// ProblemForbidden returns a forbidden problem builder. +func ProblemForbidden(detail string) *ProblemBuilder { + return Problem(http.StatusForbidden). + Type(GetProblemTypeURL("forbidden_error")). + Title("Forbidden"). + Detail(detail) +} + +// ProblemConflict returns a conflict problem builder. +func ProblemConflict(detail string) *ProblemBuilder { + return Problem(http.StatusConflict). + Type(GetProblemTypeURL("conflict_error")). + Title("Conflict"). + Detail(detail) +} + +// ProblemUnprocessable returns an unprocessable entity problem builder. +func ProblemUnprocessable(detail string) *ProblemBuilder { + return Problem(http.StatusUnprocessableEntity). + Type(GetProblemTypeURL("unprocessable_error")). + Title("Unprocessable Entity"). + Detail(detail) +} + +// ProblemInternal returns an internal server error problem builder. +func ProblemInternal(detail string) *ProblemBuilder { + return Problem(http.StatusInternalServerError). + Type(GetProblemTypeURL("server_error")). + Title("Internal Server Error"). + Detail(detail) +} + // NewBadRequestProblem returns a ready-to-use bad request problem. func NewBadRequestProblem(detail string) *ProblemDetails { return ProblemBadRequest(detail).Build() @@ -27,3 +67,28 @@ func NewBadRequestProblem(detail string) *ProblemDetails { func NewNotFoundProblem(detail string) *ProblemDetails { return ProblemNotFound(detail).Build() } + +// NewUnauthorizedProblem returns a ready-to-use unauthorized problem. +func NewUnauthorizedProblem(detail string) *ProblemDetails { + return ProblemUnauthorized(detail).Build() +} + +// NewForbiddenProblem returns a ready-to-use forbidden problem. +func NewForbiddenProblem(detail string) *ProblemDetails { + return ProblemForbidden(detail).Build() +} + +// NewConflictProblem returns a ready-to-use conflict problem. +func NewConflictProblem(detail string) *ProblemDetails { + return ProblemConflict(detail).Build() +} + +// NewUnprocessableProblem returns a ready-to-use unprocessable entity problem. +func NewUnprocessableProblem(detail string) *ProblemDetails { + return ProblemUnprocessable(detail).Build() +} + +// NewInternalProblem returns a ready-to-use internal server error problem. +func NewInternalProblem(detail string) *ProblemDetails { + return ProblemInternal(detail).Build() +} diff --git a/problem_helpers_test.go b/problem_helpers_test.go index 39fe17e..9f8d02a 100644 --- a/problem_helpers_test.go +++ b/problem_helpers_test.go @@ -19,6 +19,46 @@ func TestProblemBuilderHelpers(t *testing.T) { } } +func TestStatusProblemHelpers(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + builder func(string) *ProblemBuilder + direct func(string) *ProblemDetails + status int + title string + errType string + }{ + {"unauthorized", ProblemUnauthorized, NewUnauthorizedProblem, http.StatusUnauthorized, "Unauthorized", "unauthorized_error"}, + {"forbidden", ProblemForbidden, NewForbiddenProblem, http.StatusForbidden, "Forbidden", "forbidden_error"}, + {"conflict", ProblemConflict, NewConflictProblem, http.StatusConflict, "Conflict", "conflict_error"}, + {"unprocessable", ProblemUnprocessable, NewUnprocessableProblem, http.StatusUnprocessableEntity, "Unprocessable Entity", "unprocessable_error"}, + {"internal", ProblemInternal, NewInternalProblem, http.StatusInternalServerError, "Internal Server Error", "server_error"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + for _, got := range []*ProblemDetails{tt.builder("some detail").Build(), tt.direct("some detail")} { + if got.Status != tt.status { + t.Errorf("status = %d, want %d", got.Status, tt.status) + } + if got.Title != tt.title { + t.Errorf("title = %q, want %q", got.Title, tt.title) + } + if got.Detail != "some detail" { + t.Errorf("detail = %q", got.Detail) + } + if want := GetProblemTypeURL(tt.errType); got.Type != want || want == BlankURL { + t.Errorf("type = %q, want %q", got.Type, want) + } + } + }) + } +} + func TestDirectProblemHelpers(t *testing.T) { t.Parallel()