diff --git a/go.mod b/go.mod index 6ad7ffe..65e8f90 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module github.com/mockzilla/mockzilla-codegen-template go 1.26.8 require ( - github.com/doordash-oss/oapi-codegen-dd/v3 v3.75.11 + github.com/doordash-oss/oapi-codegen-dd/v3 v3.75.18 github.com/go-chi/chi/v5 v5.3.2 github.com/go-playground/validator/v10 v10.30.4 github.com/joho/godotenv v1.5.1 github.com/lmittmann/tint v1.1.3 - github.com/mockzilla/mockzilla/v2 v2.9.2 + github.com/mockzilla/mockzilla/v2 v2.9.3 ) require ( diff --git a/go.sum b/go.sum index ffc18d0..f099650 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8= github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/doordash-oss/oapi-codegen-dd/v3 v3.75.11 h1:b3NIu/UJ0pg3fiK16aNgBtulCzzXTU+2HDzBjQkOIa0= -github.com/doordash-oss/oapi-codegen-dd/v3 v3.75.11/go.mod h1:tOXannkMskMrmhh3dPoW0mDhqKpsC34BkHKNlw7ydmg= +github.com/doordash-oss/oapi-codegen-dd/v3 v3.75.18 h1:lCJLaKz6fItFo8htsVV6wgMS3txLN+ypBHGG8aV694g= +github.com/doordash-oss/oapi-codegen-dd/v3 v3.75.18/go.mod h1:6muR3yI4LRf8KO0awHMhLwPM92bN7hUCgv1RRt3peus= github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ= github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY= @@ -57,8 +57,8 @@ github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0= github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE= github.com/lmittmann/tint v1.1.3 h1:Hv4EaHWXQr+GTFnOU4VKf8UvAtZgn0VuKT+G0wFlO3I= github.com/lmittmann/tint v1.1.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/mockzilla/mockzilla/v2 v2.9.2 h1:xDh1MIedXDxYVx00TvoN8hgz3zwcA20ZZdbQEOimcFs= -github.com/mockzilla/mockzilla/v2 v2.9.2/go.mod h1:CESVDN8Q3wHY7+d8kJyU4g2WCpMjWrjIQOR7BLPNavo= +github.com/mockzilla/mockzilla/v2 v2.9.3 h1:ecZdl0CWerbtN9b44FMiinph8OFq03ytbHq55lPBA/Y= +github.com/mockzilla/mockzilla/v2 v2.9.3/go.mod h1:xDjmQstM5AcMUquDKP3K3cpJhxE+M0nmM+qNBb0UXTE= github.com/pb33f/jsonpath v0.8.2 h1:Ou4C7zjYClBm97dfZjDCjdZGusJoynv/vrtiEKNfj2Y= github.com/pb33f/jsonpath v0.8.2/go.mod h1:zBV5LJW4OQOPatmQE2QdKpGQJvhDTlE5IEj6ASaRNTo= github.com/pb33f/libopenapi v0.38.7 h1:Q2jfgRPdnU38WW8wQvrX2HEPGiqsxj01PX1BHmAEihc= diff --git a/pkg/hello_world/gen.go b/pkg/hello_world/gen.go index 435e3f9..dfa451e 100644 --- a/pkg/hello_world/gen.go +++ b/pkg/hello_world/gen.go @@ -53,12 +53,20 @@ type OapiHandlerError struct { Message string ParamName string ParamLocation string + + // Err is the error that caused this handler error. + Err error `json:"-"` } func (e OapiHandlerError) Error() string { return e.Message } +// Unwrap returns the underlying error, enabling errors.Is and errors.As. +func (e OapiHandlerError) Unwrap() error { + return e.Err +} + // OapiErrorResponse is the default JSON error response structure used by OapiDefaultErrorHandler. type OapiErrorResponse struct { Error string `json:"error"` @@ -139,21 +147,29 @@ func (a *HTTPAdapter) PostHello(w http.ResponseWriter, r *http.Request) { // Parse request body defer r.Body.Close() var body PostHelloBody - if err := a.jsonBodyDecoder(r.Body, &body); err != nil { + switch err := a.jsonBodyDecoder(r.Body, &body); { + case errors.Is(err, runtime.ErrRequestBodyEmpty): + // requestBody is optional, so a request carrying none leaves opts.Body + // nil rather than failing. Decoding into the zero value instead would + // hand the validator a body nobody sent, and fail on its required fields. + case err != nil: a.errHandler.HandleError(w, r, http.StatusBadRequest, OapiHandlerError{ Kind: OapiErrorKindDecode, OperationID: "PostHello", Message: err.Error(), + Err: err, }) return + default: + opts.Body = &body } - opts.Body = &body // Validate request if err := opts.Validate(); err != nil { a.errHandler.HandleError(w, r, http.StatusBadRequest, OapiHandlerError{ Kind: OapiErrorKindValidation, OperationID: "PostHello", Message: err.Error(), + Err: err, }) return } @@ -177,6 +193,7 @@ func (a *HTTPAdapter) PostHello(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "PostHello", Message: fmt.Sprintf("response validation failed: %v", err), + Err: err, }) return } diff --git a/pkg/petstore/gen.go b/pkg/petstore/gen.go index 061950d..7a779e2 100644 --- a/pkg/petstore/gen.go +++ b/pkg/petstore/gen.go @@ -53,12 +53,20 @@ type OapiHandlerError struct { Message string ParamName string ParamLocation string + + // Err is the error that caused this handler error. + Err error `json:"-"` } func (e OapiHandlerError) Error() string { return e.Message } +// Unwrap returns the underlying error, enabling errors.Is and errors.As. +func (e OapiHandlerError) Unwrap() error { + return e.Err +} + // OapiErrorResponse is the default JSON error response structure used by OapiDefaultErrorHandler. type OapiErrorResponse struct { Error string `json:"error"` @@ -150,6 +158,7 @@ func (a *HTTPAdapter) FindPets(w http.ResponseWriter, r *http.Request) { Message: err.Error(), ParamName: "limit", ParamLocation: "query", + Err: err, }) return } @@ -162,6 +171,7 @@ func (a *HTTPAdapter) FindPets(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "FindPets", Message: err.Error(), + Err: err, }) return } @@ -185,6 +195,7 @@ func (a *HTTPAdapter) FindPets(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "FindPets", Message: fmt.Sprintf("response validation failed: %v", err), + Err: err, }) return } @@ -230,6 +241,7 @@ func (a *HTTPAdapter) AddPet(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindDecode, OperationID: "AddPet", Message: err.Error(), + Err: err, }) return } @@ -240,6 +252,7 @@ func (a *HTTPAdapter) AddPet(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "AddPet", Message: err.Error(), + Err: err, }) return } @@ -263,6 +276,7 @@ func (a *HTTPAdapter) AddPet(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "AddPet", Message: fmt.Sprintf("response validation failed: %v", err), + Err: err, }) return } @@ -312,6 +326,7 @@ func (a *HTTPAdapter) FindPetByID(w http.ResponseWriter, r *http.Request) { Message: err.Error(), ParamName: "id", ParamLocation: "path", + Err: err, }) return } @@ -323,6 +338,7 @@ func (a *HTTPAdapter) FindPetByID(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "FindPetByID", Message: err.Error(), + Err: err, }) return } @@ -346,6 +362,7 @@ func (a *HTTPAdapter) FindPetByID(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "FindPetByID", Message: fmt.Sprintf("response validation failed: %v", err), + Err: err, }) return } @@ -395,6 +412,7 @@ func (a *HTTPAdapter) DeletePet(w http.ResponseWriter, r *http.Request) { Message: err.Error(), ParamName: "id", ParamLocation: "path", + Err: err, }) return } @@ -406,6 +424,7 @@ func (a *HTTPAdapter) DeletePet(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "DeletePet", Message: err.Error(), + Err: err, }) return } @@ -429,6 +448,7 @@ func (a *HTTPAdapter) DeletePet(w http.ResponseWriter, r *http.Request) { Kind: OapiErrorKindValidation, OperationID: "DeletePet", Message: fmt.Sprintf("response validation failed: %v", err), + Err: err, }) return }