Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use %w to wrap the errors #596

Merged
merged 2 commits into from Sep 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions jsoninfo/unmarshal.go
Expand Up @@ -25,7 +25,7 @@ type ObjectDecoder struct {
func NewObjectDecoder(data []byte) (*ObjectDecoder, error) {
var remainingFields map[string]json.RawMessage
if err := json.Unmarshal(data, &remainingFields); err != nil {
return nil, fmt.Errorf("failed to unmarshal extension properties: %v (%s)", err, data)
return nil, fmt.Errorf("failed to unmarshal extension properties: %w (%s)", err, data)
}
return &ObjectDecoder{
Data: data,
Expand Down Expand Up @@ -87,7 +87,7 @@ func (decoder *ObjectDecoder) DecodeStructFieldsAndExtensions(value interface{})
continue
}
}
return fmt.Errorf("failed to unmarshal property %q (%s): %v",
return fmt.Errorf("failed to unmarshal property %q (%s): %w",
field.JSONName, fieldValue.Type().String(), err)
}
if !isPtr {
Expand All @@ -109,7 +109,7 @@ func (decoder *ObjectDecoder) DecodeStructFieldsAndExtensions(value interface{})
continue
}
}
return fmt.Errorf("failed to unmarshal property %q (%s): %v",
return fmt.Errorf("failed to unmarshal property %q (%s): %w",
field.JSONName, fieldPtr.Type().String(), err)
}

Expand Down
2 changes: 1 addition & 1 deletion openapi3/components.go
Expand Up @@ -99,7 +99,7 @@ func (components *Components) Validate(ctx context.Context) (err error) {
return
}
if err = v.Validate(ctx); err != nil {
return fmt.Errorf("%s: %s", k, err)
return fmt.Errorf("%s: %w", k, err)
}
}

Expand Down
8 changes: 4 additions & 4 deletions openapi3/header.go
Expand Up @@ -71,22 +71,22 @@ func (header *Header) Validate(ctx context.Context) error {
sm.Style == SerializationSimple && !sm.Explode ||
sm.Style == SerializationSimple && sm.Explode; !smSupported {
e := fmt.Errorf("serialization method with style=%q and explode=%v is not supported by a header parameter", sm.Style, sm.Explode)
return fmt.Errorf("header schema is invalid: %v", e)
return fmt.Errorf("header schema is invalid: %w", e)
}

if (header.Schema == nil) == (header.Content == nil) {
e := fmt.Errorf("parameter must contain exactly one of content and schema: %v", header)
return fmt.Errorf("header schema is invalid: %v", e)
return fmt.Errorf("header schema is invalid: %w", e)
}
if schema := header.Schema; schema != nil {
if err := schema.Validate(ctx); err != nil {
return fmt.Errorf("header schema is invalid: %v", err)
return fmt.Errorf("header schema is invalid: %w", err)
}
}

if content := header.Content; content != nil {
if err := content.Validate(ctx); err != nil {
return fmt.Errorf("header content is invalid: %v", err)
return fmt.Errorf("header content is invalid: %w", err)
}
}
return nil
Expand Down
8 changes: 4 additions & 4 deletions openapi3/loader.go
Expand Up @@ -101,7 +101,7 @@ func (loader *Loader) loadSingleElementFromURI(ref string, rootPath *url.URL, el

resolvedPath, err := resolvePath(rootPath, parsedURL)
if err != nil {
return nil, fmt.Errorf("could not resolve path: %v", err)
return nil, fmt.Errorf("could not resolve path: %w", err)
}

data, err := loader.readURL(resolvedPath)
Expand Down Expand Up @@ -285,7 +285,7 @@ func (loader *Loader) resolveComponent(

if cursor, err = drillIntoField(cursor, pathPart); err != nil {
e := failedToResolveRefFragmentPart(ref, pathPart)
return nil, fmt.Errorf("%s: %s", e.Error(), err.Error())
return nil, fmt.Errorf("%s: %w", e, err)
}
if cursor == nil {
return nil, failedToResolveRefFragmentPart(ref, pathPart)
Expand Down Expand Up @@ -430,11 +430,11 @@ func (loader *Loader) resolveRef(doc *T, ref string, path *url.URL) (*T, string,

var resolvedPath *url.URL
if resolvedPath, err = resolvePath(path, parsedURL); err != nil {
return nil, "", nil, fmt.Errorf("error resolving path: %v", err)
return nil, "", nil, fmt.Errorf("error resolving path: %w", err)
}

if doc, err = loader.loadFromURIInternal(resolvedPath); err != nil {
return nil, "", nil, fmt.Errorf("error resolving reference %q: %v", ref, err)
return nil, "", nil, fmt.Errorf("error resolving reference %q: %w", ref, err)
}

return doc, "#" + fragment, resolvedPath, nil
Expand Down
27 changes: 15 additions & 12 deletions openapi3/loader_test.go
@@ -1,7 +1,6 @@
package openapi3

import (
"errors"
"fmt"
"net"
"net/http"
Expand Down Expand Up @@ -524,23 +523,27 @@ paths: {}
servers:
- @@@
`
for value, expected := range map[string]error{
`{url: /}`: nil,
`{url: "http://{x}.{y}.example.com"}`: errors.New("invalid servers: server has undeclared variables"),
`{url: "http://{x}.y}.example.com"}`: errors.New("invalid servers: server URL has mismatched { and }"),
`{url: "http://{x.example.com"}`: errors.New("invalid servers: server URL has mismatched { and }"),
`{url: "http://{x}.example.com", variables: {x: {default: "www"}}}`: nil,
`{url: "http://{x}.example.com", variables: {x: {default: "www", enum: ["www"]}}}`: nil,
`{url: "http://{x}.example.com", variables: {x: {enum: ["www"]}}}`: errors.New(`invalid servers: field default is required in {"enum":["www"]}`),
`{url: "http://www.example.com", variables: {x: {enum: ["www"]}}}`: errors.New("invalid servers: server has undeclared variables"),
`{url: "http://{y}.example.com", variables: {x: {enum: ["www"]}}}`: errors.New("invalid servers: server has undeclared variables"),
for value, expected := range map[string]string{
`{url: /}`: "",
`{url: "http://{x}.{y}.example.com"}`: "invalid servers: server has undeclared variables",
`{url: "http://{x}.y}.example.com"}`: "invalid servers: server URL has mismatched { and }",
`{url: "http://{x.example.com"}`: "invalid servers: server URL has mismatched { and }",
`{url: "http://{x}.example.com", variables: {x: {default: "www"}}}`: "",
`{url: "http://{x}.example.com", variables: {x: {default: "www", enum: ["www"]}}}`: "",
`{url: "http://{x}.example.com", variables: {x: {enum: ["www"]}}}`: `invalid servers: field default is required in {"enum":["www"]}`,
`{url: "http://www.example.com", variables: {x: {enum: ["www"]}}}`: "invalid servers: server has undeclared variables",
`{url: "http://{y}.example.com", variables: {x: {enum: ["www"]}}}`: "invalid servers: server has undeclared variables",
} {
t.Run(value, func(t *testing.T) {
loader := NewLoader()
doc, err := loader.LoadFromData([]byte(strings.Replace(spec, "@@@", value, 1)))
require.NoError(t, err)
err = doc.Validate(loader.Context)
require.Equal(t, expected, err)
if expected == "" {
require.NoError(t, err)
} else {
require.EqualError(t, err, expected)
}
})
}
}
4 changes: 2 additions & 2 deletions openapi3/media_type.go
Expand Up @@ -95,10 +95,10 @@ func (mediaType *MediaType) Validate(ctx context.Context) error {
} else if examples := mediaType.Examples; examples != nil {
for k, v := range examples {
if err := v.Validate(ctx); err != nil {
return fmt.Errorf("%s: %s", k, err)
return fmt.Errorf("%s: %w", k, err)
}
if err := validateExampleValue(v.Value.Value, schema.Value); err != nil {
return fmt.Errorf("%s: %s", k, err)
return fmt.Errorf("%s: %w", k, err)
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions openapi3/openapi3.go
Expand Up @@ -69,14 +69,14 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
// NOTE: only mention info/components/paths/... key in this func's errors.

{
wrap := func(e error) error { return fmt.Errorf("invalid components: %v", e) }
wrap := func(e error) error { return fmt.Errorf("invalid components: %w", e) }
if err := doc.Components.Validate(ctx); err != nil {
return wrap(err)
}
}

{
wrap := func(e error) error { return fmt.Errorf("invalid info: %v", e) }
wrap := func(e error) error { return fmt.Errorf("invalid info: %w", e) }
if v := doc.Info; v != nil {
if err := v.Validate(ctx); err != nil {
return wrap(err)
Expand All @@ -87,7 +87,7 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
}

{
wrap := func(e error) error { return fmt.Errorf("invalid paths: %v", e) }
wrap := func(e error) error { return fmt.Errorf("invalid paths: %w", e) }
if v := doc.Paths; v != nil {
if err := v.Validate(ctx); err != nil {
return wrap(err)
Expand All @@ -98,7 +98,7 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
}

{
wrap := func(e error) error { return fmt.Errorf("invalid security: %v", e) }
wrap := func(e error) error { return fmt.Errorf("invalid security: %w", e) }
if v := doc.Security; v != nil {
if err := v.Validate(ctx); err != nil {
return wrap(err)
Expand All @@ -107,7 +107,7 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
}

{
wrap := func(e error) error { return fmt.Errorf("invalid servers: %v", e) }
wrap := func(e error) error { return fmt.Errorf("invalid servers: %w", e) }
if v := doc.Servers; v != nil {
if err := v.Validate(ctx); err != nil {
return wrap(err)
Expand Down
12 changes: 6 additions & 6 deletions openapi3/parameter.go
Expand Up @@ -296,23 +296,23 @@ func (parameter *Parameter) Validate(ctx context.Context) error {
}
if !smSupported {
e := fmt.Errorf("serialization method with style=%q and explode=%v is not supported by a %s parameter", sm.Style, sm.Explode, in)
return fmt.Errorf("parameter %q schema is invalid: %v", parameter.Name, e)
return fmt.Errorf("parameter %q schema is invalid: %w", parameter.Name, e)
}

if (parameter.Schema == nil) == (parameter.Content == nil) {
e := errors.New("parameter must contain exactly one of content and schema")
return fmt.Errorf("parameter %q schema is invalid: %v", parameter.Name, e)
return fmt.Errorf("parameter %q schema is invalid: %w", parameter.Name, e)
}

if content := parameter.Content; content != nil {
if err := content.Validate(ctx); err != nil {
return fmt.Errorf("parameter %q content is invalid: %v", parameter.Name, err)
return fmt.Errorf("parameter %q content is invalid: %w", parameter.Name, err)
}
}

if schema := parameter.Schema; schema != nil {
if err := schema.Validate(ctx); err != nil {
return fmt.Errorf("parameter %q schema is invalid: %v", parameter.Name, err)
return fmt.Errorf("parameter %q schema is invalid: %w", parameter.Name, err)
}
if parameter.Example != nil && parameter.Examples != nil {
return fmt.Errorf("parameter %q example and examples are mutually exclusive", parameter.Name)
Expand All @@ -327,10 +327,10 @@ func (parameter *Parameter) Validate(ctx context.Context) error {
} else if examples := parameter.Examples; examples != nil {
for k, v := range examples {
if err := v.Validate(ctx); err != nil {
return fmt.Errorf("%s: %s", k, err)
return fmt.Errorf("%s: %w", k, err)
}
if err := validateExampleValue(v.Value.Value, schema.Value); err != nil {
return fmt.Errorf("%s: %s", k, err)
return fmt.Errorf("%s: %w", k, err)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion openapi3/schema.go
Expand Up @@ -755,7 +755,7 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)

if x := schema.Example; x != nil && !validationOpts.ExamplesValidationDisabled {
if err := validateExampleValue(x, schema); err != nil {
return fmt.Errorf("invalid schema example: %s", err)
return fmt.Errorf("invalid schema example: %w", err)
}
}

Expand Down
2 changes: 1 addition & 1 deletion openapi3/schema_formats.go
Expand Up @@ -28,7 +28,7 @@ var SchemaStringFormats = make(map[string]Format, 4)
func DefineStringFormat(name string, pattern string) {
re, err := regexp.Compile(pattern)
if err != nil {
err := fmt.Errorf("format %q has invalid pattern %q: %v", name, pattern, err)
err := fmt.Errorf("format %q has invalid pattern %q: %w", name, pattern, err)
panic(err)
}
SchemaStringFormats[name] = Format{regexp: re}
Expand Down
2 changes: 1 addition & 1 deletion openapi3/security_scheme.go
Expand Up @@ -165,7 +165,7 @@ func (ss *SecurityScheme) Validate(ctx context.Context) error {
return fmt.Errorf("security scheme of type %q should have 'flows'", ss.Type)
}
if err := flow.Validate(ctx); err != nil {
return fmt.Errorf("security scheme 'flow' is invalid: %v", err)
return fmt.Errorf("security scheme 'flow' is invalid: %w", err)
}
} else if ss.Flows != nil {
return fmt.Errorf("security scheme of type %q can't have 'flows'", ss.Type)
Expand Down
12 changes: 6 additions & 6 deletions openapi3filter/req_resp_decoder.go
Expand Up @@ -654,7 +654,7 @@ func (d *cookieParamDecoder) DecodePrimitive(param string, sm *openapi3.Serializ
return nil, found, nil
}
if err != nil {
return nil, found, fmt.Errorf("decoding param %q: %s", param, err)
return nil, found, fmt.Errorf("decoding param %q: %w", param, err)
}

val, err := parsePrimitive(cookie.Value, schema)
Expand All @@ -673,7 +673,7 @@ func (d *cookieParamDecoder) DecodeArray(param string, sm *openapi3.Serializatio
return nil, found, nil
}
if err != nil {
return nil, found, fmt.Errorf("decoding param %q: %s", param, err)
return nil, found, fmt.Errorf("decoding param %q: %w", param, err)
}
val, err := parseArray(strings.Split(cookie.Value, ","), schema)
return val, found, err
Expand All @@ -691,7 +691,7 @@ func (d *cookieParamDecoder) DecodeObject(param string, sm *openapi3.Serializati
return nil, found, nil
}
if err != nil {
return nil, found, fmt.Errorf("decoding param %q: %s", param, err)
return nil, found, fmt.Errorf("decoding param %q: %w", param, err)
}
props, err := propsFromString(cookie.Value, ",", ",")
if err != nil {
Expand Down Expand Up @@ -753,7 +753,7 @@ func makeObject(props map[string]string, schema *openapi3.SchemaRef) (map[string
if v, ok := err.(*ParseError); ok {
return nil, &ParseError{path: []interface{}{propName}, Cause: v}
}
return nil, fmt.Errorf("property %q: %s", propName, err)
return nil, fmt.Errorf("property %q: %w", propName, err)
}
obj[propName] = value
}
Expand All @@ -771,7 +771,7 @@ func parseArray(raw []string, schemaRef *openapi3.SchemaRef) ([]interface{}, err
if v, ok := err.(*ParseError); ok {
return nil, &ParseError{path: []interface{}{i}, Cause: v}
}
return nil, fmt.Errorf("item %d: %s", i, err)
return nil, fmt.Errorf("item %d: %w", i, err)
}

// If the items are nil, then the array is nil. There shouldn't be case where some values are actual primitive
Expand Down Expand Up @@ -1044,7 +1044,7 @@ func multipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.S
if v, ok := err.(*ParseError); ok {
return nil, &ParseError{path: []interface{}{name}, Cause: v}
}
return nil, fmt.Errorf("part %s: %s", name, err)
return nil, fmt.Errorf("part %s: %w", name, err)
}
values[name] = append(values[name], value)
}
Expand Down
2 changes: 1 addition & 1 deletion routers/legacy/router.go
Expand Up @@ -60,7 +60,7 @@ type Router struct {
// All operations of the document will be added to the router.
func NewRouter(doc *openapi3.T) (routers.Router, error) {
if err := doc.Validate(context.Background()); err != nil {
return nil, fmt.Errorf("validating OpenAPI failed: %v", err)
return nil, fmt.Errorf("validating OpenAPI failed: %w", err)
}
router := &Router{doc: doc}
root := router.node()
Expand Down