diff --git a/.github/docs/openapi2conv.txt b/.github/docs/openapi2conv.txt index e24925aa3..2930594d7 100644 --- a/.github/docs/openapi2conv.txt +++ b/.github/docs/openapi2conv.txt @@ -19,12 +19,12 @@ func FromV3Responses(responses map[string]*openapi3.ResponseRef, components *ope func FromV3SchemaRef(schema *openapi3.SchemaRef, components *openapi3.Components) (*openapi2.SchemaRef, *openapi2.Parameter) func FromV3Schemas(schemas map[string]*openapi3.SchemaRef, components *openapi3.Components) (map[string]*openapi2.SchemaRef, map[string]*openapi2.Parameter) func FromV3SecurityRequirements(requirements openapi3.SecurityRequirements) openapi2.SecurityRequirements -func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*openapi2.SecurityScheme, error) +func FromV3SecurityScheme(ref *openapi3.SecuritySchemeRef) (*openapi2.SecurityScheme, error) func ToV3(doc2 *openapi2.T) (*openapi3.T, error) ToV3 converts an OpenAPIv2 spec to an OpenAPIv3 spec func ToV3Headers(defs map[string]*openapi2.Header) openapi3.Headers -func ToV3Operation(doc2 *openapi2.T, components *openapi3.Components, pathItem *openapi2.PathItem, operation *openapi2.Operation, consumes []string) (*openapi3.Operation, error) +func ToV3Operation(components *openapi3.Components, pathItem *openapi2.PathItem, operation *openapi2.Operation, consumes []string) (*openapi3.Operation, error) func ToV3Parameter(components *openapi3.Components, parameter *openapi2.Parameter, consumes []string) (*openapi3.ParameterRef, *openapi3.RequestBodyRef, map[string]*openapi3.SchemaRef, error) func ToV3PathItem(doc2 *openapi2.T, components *openapi3.Components, pathItem *openapi2.PathItem, consumes []string) (*openapi3.PathItem, error) func ToV3Ref(ref string) string diff --git a/.github/docs/openapi3.txt b/.github/docs/openapi3.txt index 3f04f78ec..545ed48ab 100644 --- a/.github/docs/openapi3.txt +++ b/.github/docs/openapi3.txt @@ -121,11 +121,6 @@ var IncludeOrigin = false FUNCTIONS -func BoolPtr(value bool) *bool - BoolPtr is a helper for defining OpenAPI schemas. - - Deprecated: Use Ptr instead. - func DefaultRefNameResolver(doc *T, ref ComponentRef) string DefaultRefResolver is a default implementation of refNameResolver for the InternalizeRefs function. @@ -138,7 +133,7 @@ func DefaultRefNameResolver(doc *T, ref ComponentRef) string - Cutting the "#/components/" part. - Cutting the file extensions (.yaml/.json) from documents. - Trimming the common directory with the root spec. - - Replace invalid characters with with underscores. + - Replace invalid characters with underscores. This is an injective mapping over a "reasonable" amount of the possible openapi spec domain space but is not perfect. There might be edge cases. @@ -174,19 +169,6 @@ func DefineStringFormatValidator(name string, validator StringFormatValidator) DefineStringFormatValidator defines a custom format validator for a given string format. -func Float64Ptr(value float64) *float64 - Float64Ptr is a helper for defining OpenAPI schemas. - - Deprecated: Use Ptr instead. - -func Int64Ptr(value int64) *int64 - Int64Ptr is a helper for defining OpenAPI schemas. - - Deprecated: Use Ptr instead. - -func Ptr[T any](value T) *T - Ptr is a helper for defining OpenAPI schemas. - func ReadFromFile(loader *Loader, location *url.URL) ([]byte, error) ReadFromFile is a ReadFromURIFunc which reads local file URIs. @@ -236,11 +218,6 @@ func RegisterArrayUniqueItemsChecker(fn SliceUniqueItemsChecker) RegisterArrayUniqueItemsChecker is used to register a customized function used to check if JSON array have unique items. -func Uint64Ptr(value uint64) *uint64 - Uint64Ptr is a helper for defining OpenAPI schemas. - - Deprecated: Use Ptr instead. - func ValidateIdentifier(value string) error ValidateIdentifier returns an error if the given component name does not match IdentifierRegExp. @@ -364,7 +341,7 @@ func (x *CallbackRef) Validate(ctx context.Context, opts ...ValidationOption) er Validate returns an error if CallbackRef does not comply with the OpenAPI spec. -type Callbacks map[string]*CallbackRef +type Callbacks map[string]*CallbackRef // Callbacks represents components' named callbacks func (m Callbacks) JSONLookup(token string) (any, error) JSONLookup implements @@ -591,7 +568,7 @@ func (x *ExampleRef) Validate(ctx context.Context, opts ...ValidationOption) err Validate returns an error if ExampleRef does not comply with the OpenAPI spec. -type Examples map[string]*ExampleRef +type Examples map[string]*ExampleRef // Examples represents components' named examples func (m Examples) JSONLookup(token string) (any, error) JSONLookup implements @@ -731,7 +708,7 @@ func (x *HeaderRef) Validate(ctx context.Context, opts ...ValidationOption) erro Validate returns an error if HeaderRef does not comply with the OpenAPI spec. -type Headers map[string]*HeaderRef +type Headers map[string]*HeaderRef // Headers represents components' named headers func (m Headers) JSONLookup(token string) (any, error) JSONLookup implements @@ -866,7 +843,7 @@ func (x *LinkRef) UnmarshalJSON(data []byte) error func (x *LinkRef) Validate(ctx context.Context, opts ...ValidationOption) error Validate returns an error if LinkRef does not comply with the OpenAPI spec. -type Links map[string]*LinkRef +type Links map[string]*LinkRef // Links represents components' named links func (m Links) JSONLookup(token string) (any, error) JSONLookup implements @@ -1259,7 +1236,7 @@ func (parameters Parameters) Validate(ctx context.Context, opts ...ValidationOpt Validate returns an error if Parameters does not comply with the OpenAPI spec. -type ParametersMap map[string]*ParameterRef +type ParametersMap map[string]*ParameterRef // ParametersMap represents components' named parameters func (m ParametersMap) JSONLookup(token string) (any, error) JSONLookup implements @@ -1432,7 +1409,7 @@ type RegexMatcher interface { MatchString(s string) bool } -type RequestBodies map[string]*RequestBodyRef +type RequestBodies map[string]*RequestBodyRef // RequestBodies represents components' named request bodies func (m RequestBodies) JSONLookup(token string) (any, error) JSONLookup implements @@ -1562,7 +1539,7 @@ func (response *Response) WithJSONSchema(schema *Schema) *Response func (response *Response) WithJSONSchemaRef(schema *SchemaRef) *Response -type ResponseBodies map[string]*ResponseRef +type ResponseBodies map[string]*ResponseRef // ResponseBodies represents components' named response bodies func (m ResponseBodies) JSONLookup(token string) (any, error) JSONLookup implements @@ -2062,7 +2039,7 @@ func WithStringFormatValidators(validators map[string]StringFormatValidator) Sch These validators are checked before global SchemaStringFormats and allow different validations for the same format name across different specs. -type Schemas map[string]*SchemaRef +type Schemas map[string]*SchemaRef // Schemas represents components' named schemas func (m Schemas) JSONLookup(token string) (any, error) JSONLookup implements @@ -2189,7 +2166,7 @@ func (x *SecuritySchemeRef) Validate(ctx context.Context, opts ...ValidationOpti Validate returns an error if SecuritySchemeRef does not comply with the OpenAPI spec. -type SecuritySchemes map[string]*SecuritySchemeRef +type SecuritySchemes map[string]*SecuritySchemeRef // SecuritySchemes represents components' named security schemes func (m SecuritySchemes) JSONLookup(token string) (any, error) JSONLookup implements diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 5063fb351..ffe527217 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -25,29 +25,10 @@ jobs: name: ${{ matrix.go }} on ${{ matrix.os }} steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v6 with: go-version: ${{ matrix.go }} - - id: go-cache-paths - run: | - echo "::set-output name=go-build::$(go env GOCACHE)" - echo "::set-output name=go-mod::$(go env GOMODCACHE)" - - run: echo ${{ steps.go-cache-paths.outputs.go-build }} - - run: echo ${{ steps.go-cache-paths.outputs.go-mod }} - - - name: Go Build Cache - uses: actions/cache@v3 - with: - path: ${{ steps.go-cache-paths.outputs.go-build }} - key: ${{ runner.os }}-go-${{ matrix.go }}-build-${{ hashFiles('**/go.sum') }} - - - name: Go Mod Cache (go>=1.15) - uses: actions/cache@v3 - with: - path: ${{ steps.go-cache-paths.outputs.go-mod }} - key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} - - name: Test suite fixtures cache uses: actions/cache@v3 with: @@ -59,7 +40,7 @@ jobs: - if: runner.os == 'Linux' run: sudo apt install silversearcher-ag - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - run: go generate ./... - run: git --no-pager diff --exit-code @@ -212,11 +193,11 @@ jobs: check-goimports: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 with: - go-version: '>=1.17.0' - - run: go install github.com/incu6us/goimports-reviser/v2@latest + go-version: '1.26' + - run: go install github.com/incu6us/goimports-reviser/v3@latest - run: which goimports-reviser - - run: find . -type f -iname '*.go' ! -iname '*.pb.go' -exec goimports-reviser -file-path {} \; + - run: find . -type f -iname '*.go' ! -iname '*.pb.go' -exec goimports-reviser {} \; - run: git --no-pager diff --exit-code diff --git a/README.md b/README.md index 75eea45a3..0d64ea0f6 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Be sure to check [OpenAPI Initiative](https://github.com/OAI)'s [great tooling l # Some recipes ## Validating an OpenAPI document ```shell -go run github.com/getkin/kin-openapi/cmd/validate@latest [--circular] [--defaults] [--examples] [--ext] [--patterns] -- +go run github.com/getkin/kin-openapi/cmd/validate@latest [--defaults] [--examples] [--ext] [--patterns] -- ``` ## Loading OpenAPI document @@ -317,6 +317,7 @@ for _, path := range doc.Paths.InMatchingOrder() { * `openapi3.Schema.ExclusiveMin` and `openapi3.Schema.ExclusiveMax` fields changed from `bool` to `ExclusiveBound` (a union type holding `*bool` for OpenAPI 3.0 or `*float64` for OpenAPI 3.1). * `openapi3.Schema.PrefixItems` field changed from `[]*SchemaRef` to `SchemaRefs`. * `openapi3.Schema.UnevaluatedItems` and `openapi3.Schema.UnevaluatedProperties` fields changed from `*SchemaRef` to `BoolSchema` (a union type accepting either a boolean or a schema object). +* Removed `openapi3.*Ptr(..)` funcs: they all can be replaced with `new(..)` since Go 1.26 ### v0.135.0 * `openapi3.MediaType.Encoding` field type changed from `map[string]*Encoding` to `Encodings` diff --git a/go.mod b/go.mod index 6a017bd21..6af4efeab 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/getkin/kin-openapi -go 1.26.2 +go 1.26 require ( github.com/go-openapi/jsonpointer v0.21.0 diff --git a/openapi2/openapi2.go b/openapi2/openapi2.go index bd3375339..86eb8c9da 100644 --- a/openapi2/openapi2.go +++ b/openapi2/openapi2.go @@ -2,6 +2,7 @@ package openapi2 import ( "encoding/json" + "maps" "github.com/getkin/kin-openapi/openapi3" ) @@ -30,9 +31,7 @@ type T struct { // MarshalJSON returns the JSON encoding of T. func (doc T) MarshalJSON() ([]byte, error) { m := make(map[string]any, 15+len(doc.Extensions)) - for k, v := range doc.Extensions { - m[k] = v - } + maps.Copy(m, doc.Extensions) m["swagger"] = doc.Swagger m["info"] = doc.Info if x := doc.ExternalDocs; x != nil { diff --git a/openapi2/operation.go b/openapi2/operation.go index 64f10d1f1..be73f9423 100644 --- a/openapi2/operation.go +++ b/openapi2/operation.go @@ -2,6 +2,7 @@ package openapi2 import ( "encoding/json" + "maps" "github.com/getkin/kin-openapi/openapi3" ) @@ -26,9 +27,7 @@ type Operation struct { // MarshalJSON returns the JSON encoding of Operation. func (operation Operation) MarshalJSON() ([]byte, error) { m := make(map[string]any, 12+len(operation.Extensions)) - for k, v := range operation.Extensions { - m[k] = v - } + maps.Copy(m, operation.Extensions) if x := operation.Summary; x != "" { m["summary"] = x } diff --git a/openapi2/parameter.go b/openapi2/parameter.go index 99dc92bc9..796cb204a 100644 --- a/openapi2/parameter.go +++ b/openapi2/parameter.go @@ -2,6 +2,7 @@ package openapi2 import ( "encoding/json" + "maps" "github.com/getkin/kin-openapi/openapi3" ) @@ -45,9 +46,7 @@ func (parameter Parameter) MarshalJSON() ([]byte, error) { } m := make(map[string]any, 24+len(parameter.Extensions)) - for k, v := range parameter.Extensions { - m[k] = v - } + maps.Copy(m, parameter.Extensions) if x := parameter.In; x != "" { m["in"] = x diff --git a/openapi2/path_item.go b/openapi2/path_item.go index 624cc74dc..446e444cd 100644 --- a/openapi2/path_item.go +++ b/openapi2/path_item.go @@ -3,6 +3,7 @@ package openapi2 import ( "encoding/json" "fmt" + "maps" "net/http" "github.com/getkin/kin-openapi/openapi3" @@ -30,9 +31,7 @@ func (pathItem PathItem) MarshalJSON() ([]byte, error) { } m := make(map[string]any, 8+len(pathItem.Extensions)) - for k, v := range pathItem.Extensions { - m[k] = v - } + maps.Copy(m, pathItem.Extensions) if x := pathItem.Delete; x != nil { m["delete"] = x } diff --git a/openapi2/refs.go b/openapi2/refs.go index 36f92a19d..6690ee5d1 100644 --- a/openapi2/refs.go +++ b/openapi2/refs.go @@ -26,8 +26,6 @@ type SchemaRef struct { var _ jsonpointer.JSONPointable = (*SchemaRef)(nil) -func (x *SchemaRef) isEmpty() bool { return x == nil || x.Ref == "" && x.Value == nil } - // RefString returns the $ref value. func (x *SchemaRef) RefString() string { return x.Ref } @@ -37,16 +35,6 @@ func (x *SchemaRef) CollectionName() string { return "schemas" } // RefPath returns the path of the $ref relative to the root document. func (x *SchemaRef) RefPath() *url.URL { return copyURI(x.refPath) } -func (x *SchemaRef) setRefPath(u *url.URL) { - // Once the refPath is set don't override. References can be loaded - // multiple times not all with access to the correct path info. - if x.refPath != nil { - return - } - - x.refPath = copyURI(u) -} - // MarshalYAML returns the YAML encoding of SchemaRef. func (x SchemaRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { diff --git a/openapi2/response.go b/openapi2/response.go index 3a2983ce1..0bad9ee18 100644 --- a/openapi2/response.go +++ b/openapi2/response.go @@ -2,6 +2,7 @@ package openapi2 import ( "encoding/json" + "maps" "github.com/getkin/kin-openapi/openapi3" ) @@ -24,9 +25,7 @@ func (response Response) MarshalJSON() ([]byte, error) { } m := make(map[string]any, 4+len(response.Extensions)) - for k, v := range response.Extensions { - m[k] = v - } + maps.Copy(m, response.Extensions) if x := response.Description; x != "" { m["description"] = x } diff --git a/openapi2/schema.go b/openapi2/schema.go index 16063fa3e..af5264747 100644 --- a/openapi2/schema.go +++ b/openapi2/schema.go @@ -2,6 +2,7 @@ package openapi2 import ( "encoding/json" + "maps" "strings" "github.com/getkin/kin-openapi/openapi3" @@ -75,9 +76,7 @@ func (schema Schema) MarshalJSON() ([]byte, error) { // MarshalYAML returns the YAML encoding of Schema. func (schema Schema) MarshalYAML() (any, error) { m := make(map[string]any, 36+len(schema.Extensions)) - for k, v := range schema.Extensions { - m[k] = v - } + maps.Copy(m, schema.Extensions) if x := schema.AllOf; len(x) != 0 { m["allOf"] = x diff --git a/openapi2/security_scheme.go b/openapi2/security_scheme.go index cd6e6a5dd..b4674ce2d 100644 --- a/openapi2/security_scheme.go +++ b/openapi2/security_scheme.go @@ -2,6 +2,7 @@ package openapi2 import ( "encoding/json" + "maps" "github.com/getkin/kin-openapi/openapi3" ) @@ -31,9 +32,7 @@ func (securityScheme SecurityScheme) MarshalJSON() ([]byte, error) { } m := make(map[string]any, 10+len(securityScheme.Extensions)) - for k, v := range securityScheme.Extensions { - m[k] = v - } + maps.Copy(m, securityScheme.Extensions) if x := securityScheme.Description; x != "" { m["description"] = x } diff --git a/openapi2conv/issue1008_test.go b/openapi2conv/issue1008_test.go index 4d8dfe5ef..1dcad12a4 100644 --- a/openapi2conv/issue1008_test.go +++ b/openapi2conv/issue1008_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "testing" "github.com/stretchr/testify/assert" @@ -43,7 +42,7 @@ paths: v3, err := v2v3YAML(v2) require.NoError(t, err) - err = v3.Validate(context.Background()) + err = v3.Validate(t.Context()) require.NoError(t, err) assert.Equal(t, []string{"alpaca", "bee", "zebra"}, v3.Paths.Value("/ping").Post.RequestBody.Value.Content.Get("multipart/form-data").Schema.Value.Required) } diff --git a/openapi2conv/issue1016_test.go b/openapi2conv/issue1016_test.go index acd87d077..8829a7866 100644 --- a/openapi2conv/issue1016_test.go +++ b/openapi2conv/issue1016_test.go @@ -1,12 +1,12 @@ package openapi2conv import ( - "context" "encoding/json" "testing" - "github.com/getkin/kin-openapi/openapi2" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi2" ) func TestIssue1016(t *testing.T) { @@ -75,7 +75,7 @@ func TestIssue1016(t *testing.T) { doc3, err := v2v3YAML(v2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) require.Equal(t, "#/components/schemas/Pet", doc3.Components.Schemas["PetDirectory"].Value.AdditionalProperties.Schema.Ref) } diff --git a/openapi2conv/issue1049_test.go b/openapi2conv/issue1049_test.go index 04ddf8581..aba1fcdc4 100644 --- a/openapi2conv/issue1049_test.go +++ b/openapi2conv/issue1049_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "encoding/json" "testing" @@ -81,6 +80,6 @@ func TestIssue1049(t *testing.T) { const expected = `{"components":{"schemas":{"BaseDictResp":{"description":"BaseDictResp description","properties":{"key":{"description":"key of map","type":"string"},"value":{"description":"value of map","type":"string"}},"title":"BaseDictResp","type":"object"},"ResponseOfMap":{"properties":{"data":{"additionalProperties":{"items":{"$ref":"#/components/schemas/BaseDictResp"},"type":"array"},"description":"response data","type":"object"}},"title":"ResponseOfMap","type":"object"}}},"info":{"description":"Test for additionalProperties","title":"API Test","version":"v1"},"openapi":"3.0.3","paths":{"/map":{"post":{"description":"api test description","operationId":"apiTestUsingPOST","responses":{"200":{"content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseOfMap"}}},"description":"OK"}},"summary":"api test summary"}}},"servers":[{"url":"https://Test/"}]}` require.JSONEq(t, expected, string(spec3)) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) } diff --git a/openapi2conv/issue1062_test.go b/openapi2conv/issue1062_test.go index 6c1dd90e7..65af5b0b5 100644 --- a/openapi2conv/issue1062_test.go +++ b/openapi2conv/issue1062_test.go @@ -1,11 +1,13 @@ -package openapi2conv +package openapi2conv_test import ( "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/oasdiff/yaml" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi2conv" + "github.com/getkin/kin-openapi/openapi3" ) // Regression test for #1062. @@ -57,17 +59,18 @@ components: ` var doc3 openapi3.T - require.NoError(t, yaml.Unmarshal([]byte(v3Spec), &doc3), "unmarshal v3 spec") + err := yaml.Unmarshal([]byte(v3Spec), &doc3) + require.NoError(t, err, "unmarshal v3 spec") // Pre-fix: this call panicked with // "runtime error: invalid memory reference or nil pointer dereference" // inside FromV3SchemaRef when it deref'd nil components.Schemas. - v2, err := FromV3(&doc3) + doc2, err := openapi2conv.FromV3(&doc3) require.NoError(t, err, "FromV3 must not error on form-data array of $refs") - require.NotNil(t, v2) + require.NotNil(t, doc2) // Sanity: the operation made it through to v2 with a formData parameter. - op := v2.Paths["/v1/upload"].Post + op := doc2.Paths["/v1/upload"].Post require.NotNil(t, op, "POST /v1/upload should be present after conversion") var sawDocuments bool for _, p := range op.Parameters { diff --git a/openapi2conv/issue1069_test.go b/openapi2conv/issue1069_test.go index f7bb8bcdc..06ffbca8a 100644 --- a/openapi2conv/issue1069_test.go +++ b/openapi2conv/issue1069_test.go @@ -1,14 +1,14 @@ package openapi2conv import ( - "context" "testing" - "github.com/getkin/kin-openapi/openapi2" - "github.com/getkin/kin-openapi/openapi3" "github.com/oasdiff/yaml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi2" + "github.com/getkin/kin-openapi/openapi3" ) func TestIssue1069V2ToV3(t *testing.T) { @@ -99,7 +99,7 @@ paths: t.Run(tt.name, func(t *testing.T) { v3, err := v2v3YAML([]byte(tt.v2Spec)) require.NoError(t, err) - err = v3.Validate(context.Background()) + err = v3.Validate(t.Context()) require.NoError(t, err) tt.validate(t, v3) }) diff --git a/openapi2conv/issue187_test.go b/openapi2conv/issue187_test.go index 4cec87532..5c0718bd2 100644 --- a/openapi2conv/issue187_test.go +++ b/openapi2conv/issue187_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "encoding/json" "testing" @@ -106,7 +105,7 @@ func TestIssue187(t *testing.T) { const expected = `{"components":{"schemas":{"model.ProductSearchAttributeRequest":{"properties":{"filterField":{"type":"string"},"filterKey":{"type":"string"},"type":{"type":"string"},"values":{"$ref":"#/components/schemas/model.ProductSearchAttributeValueRequest"}},"title":"model.ProductSearchAttributeRequest","type":"object"},"model.ProductSearchAttributeValueRequest":{"properties":{"imageUrl":{"type":"string"},"text":{"type":"string"}},"title":"model.ProductSearchAttributeValueRequest","type":"object"}}},"info":{"contact":{"email":"test@test.com","name":"Test"},"description":"Test Golang Application","title":"Test","version":"1.0"},"openapi":"3.0.3","paths":{"/me":{"get":{"operationId":"someTest","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/model.ProductSearchAttributeRequest"}}},"description":"successful operation"}},"summary":"Some test","tags":["probe"]}}}}` require.JSONEq(t, expected, string(spec3)) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) } @@ -165,7 +164,7 @@ paths: ` require.YAMLEq(t, expected, string(spec3)) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) } diff --git a/openapi2conv/issue440_test.go b/openapi2conv/issue440_test.go index 5c9f67dc0..e4342850b 100644 --- a/openapi2conv/issue440_test.go +++ b/openapi2conv/issue440_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "encoding/json" "os" "testing" @@ -22,7 +21,7 @@ func TestIssue440(t *testing.T) { doc3, err := ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) require.Equal(t, openapi3.Servers{ {URL: "https://petstore.swagger.io/v2"}, @@ -34,7 +33,7 @@ func TestIssue440(t *testing.T) { doc2.BasePath = "" doc3, err = ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) require.Equal(t, openapi3.Servers{ {URL: "https://your-bot-domain.de/"}, @@ -46,4 +45,5 @@ func TestIssue440(t *testing.T) { doc3, err = ToV3(&doc2) require.Error(t, err) require.ErrorContains(t, err, `invalid host`) + require.Nil(t, doc3) } diff --git a/openapi2conv/issue847_test.go b/openapi2conv/issue847_test.go index 79dbb21ee..6f7540fac 100644 --- a/openapi2conv/issue847_test.go +++ b/openapi2conv/issue847_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -32,7 +31,7 @@ paths: v3, err := v2v3YAML(v2) require.NoError(t, err) - err = v3.Validate(context.Background()) + err = v3.Validate(t.Context()) require.NoError(t, err) require.Equal(t, []string{"file"}, v3.Paths.Value("/ping").Post.RequestBody.Value.Content["multipart/form-data"].Schema.Value.Required) diff --git a/openapi2conv/issue979_test.go b/openapi2conv/issue979_test.go index 8d87902c9..acca80c35 100644 --- a/openapi2conv/issue979_test.go +++ b/openapi2conv/issue979_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "encoding/json" "testing" @@ -57,7 +56,7 @@ func TestIssue979(t *testing.T) { doc3, err := ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) require.Equal(t, &openapi3.Types{"string"}, doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value.Type) diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go index 8084fac5f..1473db6a7 100644 --- a/openapi2conv/openapi2_conv.go +++ b/openapi2conv/openapi2_conv.go @@ -4,6 +4,7 @@ import ( "cmp" "errors" "fmt" + "maps" "net/url" "slices" "strings" @@ -123,7 +124,7 @@ func ToV3PathItem(doc2 *openapi2.T, components *openapi3.Components, pathItem *o Extensions: stripNonExtensions(pathItem.Extensions), } for method, operation := range pathItem.Operations() { - doc3Operation, err := ToV3Operation(doc2, components, pathItem, operation, consumes) + doc3Operation, err := ToV3Operation(components, pathItem, operation, consumes) if err != nil { return nil, err } @@ -145,7 +146,7 @@ func ToV3PathItem(doc2 *openapi2.T, components *openapi3.Components, pathItem *o return doc3, nil } -func ToV3Operation(doc2 *openapi2.T, components *openapi3.Components, pathItem *openapi2.PathItem, operation *openapi2.Operation, consumes []string) (*openapi3.Operation, error) { +func ToV3Operation(components *openapi3.Components, pathItem *openapi2.PathItem, operation *openapi2.Operation, consumes []string) (*openapi3.Operation, error) { if operation == nil { return nil, nil } @@ -639,9 +640,7 @@ func ToV3SecurityScheme(securityScheme *openapi2.SecurityScheme) (*openapi3.Secu flows := &openapi3.OAuthFlows{} result.Flows = flows scopesMap := make(map[string]string) - for scope, desc := range securityScheme.Scopes { - scopesMap[scope] = desc - } + maps.Copy(scopesMap, securityScheme.Scopes) flow := &openapi3.OAuthFlow{ AuthorizationURL: securityScheme.AuthorizationURL, TokenURL: securityScheme.TokenURL, @@ -767,7 +766,7 @@ func FromV3(doc3 *openapi3.T) (*openapi2.T, error) { if m := doc3.Components.SecuritySchemes; m != nil { doc2SecuritySchemes := make(map[string]*openapi2.SecurityScheme) for id, securityScheme := range m { - v, err := FromV3SecurityScheme(doc3, securityScheme) + v, err := FromV3SecurityScheme(securityScheme) if err != nil { return nil, err } @@ -876,16 +875,10 @@ func FromV3SchemaRef(schema *openapi3.SchemaRef, components *openapi3.Components if schema.Value != nil { if schema.Value.Type.Is("string") && schema.Value.Format == "binary" { paramType := &openapi3.Types{"file"} - required := false - value, _ := schema.Value.Extensions["x-formData-name"] + value := schema.Value.Extensions["x-formData-name"] originalName, _ := value.(string) - for _, prop := range schema.Value.Required { - if originalName == prop { - required = true - break - } - } + required := slices.Contains(schema.Value.Required, originalName) return nil, &openapi2.Parameter{ In: "formData", Name: originalName, @@ -1037,13 +1030,7 @@ func FromV3RequestBodyFormData(mediaType *openapi3.MediaType) openapi2.Parameter if val.Format == "binary" { typ = &openapi3.Types{"file"} } - required := false - for _, name := range val.Required { - if name == propName { - required = true - break - } - } + required := slices.Contains(val.Required, propName) var v2Items *openapi2.SchemaRef if val.Items != nil { @@ -1259,7 +1246,7 @@ func FromV3Headers(defs openapi3.Headers, components *openapi3.Components) (map[ return headers, nil } -func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*openapi2.SecurityScheme, error) { +func FromV3SecurityScheme(ref *openapi3.SecuritySchemeRef) (*openapi2.SecurityScheme, error) { securityScheme := ref.Value if securityScheme == nil { return nil, nil @@ -1316,9 +1303,7 @@ func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*o } result.Scopes = make(map[string]string, len(flow.Scopes)) - for scope, desc := range flow.Scopes { - result.Scopes[scope] = desc - } + maps.Copy(result.Scopes, flow.Scopes) } default: return nil, fmt.Errorf("unsupported security scheme type %q", securityScheme.Type) @@ -1363,12 +1348,11 @@ func compareParameters(a, b *openapi2.Parameter) int { return cmp.Compare(a.Ref, b.Ref) } -// boolPtr returns a pointer to a bool, or nil if the value is false (to avoid storing empty values) func boolPtr(b bool) *bool { - if !b { - return nil + if b { + return new(b) } - return &b + return nil } // exclusiveBoundToBool converts an ExclusiveBound to a bool for OpenAPI 2.0 compatibility diff --git a/openapi2conv/openapi2_conv_test.go b/openapi2conv/openapi2_conv_test.go index ce3423787..2a3c1410e 100644 --- a/openapi2conv/openapi2_conv_test.go +++ b/openapi2conv/openapi2_conv_test.go @@ -1,7 +1,6 @@ package openapi2conv import ( - "context" "encoding/json" "testing" @@ -20,7 +19,7 @@ func TestConvOpenAPIV3ToV2(t *testing.T) { sl := openapi3.NewLoader() err = sl.ResolveRefsIn(&doc3, nil) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) } @@ -40,7 +39,7 @@ func TestConvOpenAPIV3ToV2WithReqBody(t *testing.T) { sl := openapi3.NewLoader() err = sl.ResolveRefsIn(&doc3, nil) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) } @@ -58,7 +57,7 @@ func TestConvOpenAPIV2ToV3(t *testing.T) { doc3, err := ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) data, err := json.Marshal(doc3) require.NoError(t, err) @@ -119,7 +118,7 @@ func TestConvOpenAPIV2ToV3WithAdditionalPropertiesSchemaRef(t *testing.T) { doc3, err := ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) responseSchema := doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value @@ -184,7 +183,7 @@ func TestConvOpenAPIV2ToV3WithNestedAdditionalPropertiesSchemaRef(t *testing.T) doc3, err := ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) responseSchema := doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value @@ -263,7 +262,7 @@ func TestConvOpenAPIV2ToV3WithAllOfInsideAdditionalProperties(t *testing.T) { doc3, err := ToV3(&doc2) require.NoError(t, err) - err = doc3.Validate(context.Background()) + err = doc3.Validate(t.Context()) require.NoError(t, err) responseSchema := doc3.Paths.Value("/v1/objStatus").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value diff --git a/openapi3/additionalProperties_test.go b/openapi3/additionalProperties_test.go index 46cf0dbe8..2fab0a66d 100644 --- a/openapi3/additionalProperties_test.go +++ b/openapi3/additionalProperties_test.go @@ -2,7 +2,6 @@ package openapi3_test import ( "bytes" - "context" "os" "testing" @@ -13,7 +12,6 @@ import ( ) func TestMarshalAdditionalProperties(t *testing.T) { - ctx := context.Background() data, err := os.ReadFile("testdata/test.openapi.additionalproperties.yml") require.NoError(t, err) @@ -22,7 +20,7 @@ func TestMarshalAdditionalProperties(t *testing.T) { spec, err := loader.LoadFromData(data) require.NoError(t, err) - err = spec.Validate(ctx) + err = spec.Validate(t.Context()) require.NoError(t, err) var buf bytes.Buffer @@ -35,6 +33,6 @@ func TestMarshalAdditionalProperties(t *testing.T) { spec2, err := loader.LoadFromData(buf.Bytes()) require.NoError(t, err) - err = spec2.Validate(ctx) + err = spec2.Validate(t.Context()) require.NoError(t, err) } diff --git a/openapi3/components.go b/openapi3/components.go index 3b8a5423d..b1109a9c9 100644 --- a/openapi3/components.go +++ b/openapi3/components.go @@ -9,15 +9,15 @@ import ( "github.com/go-openapi/jsonpointer" ) -type Callbacks map[string]*CallbackRef -type Examples map[string]*ExampleRef -type Headers map[string]*HeaderRef -type Links map[string]*LinkRef -type ParametersMap map[string]*ParameterRef -type RequestBodies map[string]*RequestBodyRef -type ResponseBodies map[string]*ResponseRef -type Schemas map[string]*SchemaRef -type SecuritySchemes map[string]*SecuritySchemeRef +type Callbacks map[string]*CallbackRef // Callbacks represents components' named callbacks +type Examples map[string]*ExampleRef // Examples represents components' named examples +type Headers map[string]*HeaderRef // Headers represents components' named headers +type Links map[string]*LinkRef // Links represents components' named links +type ParametersMap map[string]*ParameterRef // ParametersMap represents components' named parameters +type RequestBodies map[string]*RequestBodyRef // RequestBodies represents components' named request bodies +type ResponseBodies map[string]*ResponseRef // ResponseBodies represents components' named response bodies +type Schemas map[string]*SchemaRef // Schemas represents components' named schemas +type SecuritySchemes map[string]*SecuritySchemeRef // SecuritySchemes represents components' named security schemes // Components is specified by OpenAPI/Swagger standard version 3. // See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#components-object diff --git a/openapi3/content.go b/openapi3/content.go index 77db5c0a6..8bf7921a5 100644 --- a/openapi3/content.go +++ b/openapi3/content.go @@ -9,7 +9,7 @@ import ( type Content map[string]*MediaType func NewContent() Content { - return make(map[string]*MediaType) + return make(Content) } func NewContentWithSchema(schema *Schema, consumes []string) Content { @@ -109,8 +109,7 @@ func (content Content) Validate(ctx context.Context, opts ...ValidationOption) e ctx = WithValidationOptions(ctx, opts...) for _, k := range componentNames(content) { - v := content[k] - if err := v.Validate(ctx); err != nil { + if err := content[k].Validate(ctx); err != nil { return err } } diff --git a/openapi3/discriminator_mapping_refs_test.go b/openapi3/discriminator_mapping_refs_test.go index 19579e8cb..fab0ae1d9 100644 --- a/openapi3/discriminator_mapping_refs_test.go +++ b/openapi3/discriminator_mapping_refs_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "strings" "testing" @@ -13,7 +12,7 @@ import ( // This test demonstrates the issue that discriminator mapping values, which are // JSON schema references serialized as plain strings, are not handled by InternalizeRefs. func TestDiscriminatorMappingRefsInternalize(t *testing.T) { - ctx := context.Background() + ctx := t.Context() // Load the spec with external discriminator mapping refs sl := NewLoader() diff --git a/openapi3/encoding_test.go b/openapi3/encoding_test.go index 8f256a345..807e33ce2 100644 --- a/openapi3/encoding_test.go +++ b/openapi3/encoding_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "encoding/json" "testing" @@ -15,17 +14,17 @@ func TestEncodingJSON(t *testing.T) { require.NotEmpty(t, data) t.Log("Unmarshal *openapi3.Encoding from JSON") - docA := &Encoding{} - err = json.Unmarshal(encodingJSON, &docA) + enc := &Encoding{} + err = json.Unmarshal(encodingJSON, &enc) require.NoError(t, err) - require.NotEmpty(t, docA) + require.NotEmpty(t, enc) t.Log("Validate *openapi3.Encoding") - err = docA.Validate(context.Background()) + err = enc.Validate(t.Context()) require.NoError(t, err) t.Log("Ensure representations match") - dataA, err := json.Marshal(docA) + dataA, err := json.Marshal(enc) require.NoError(t, err) require.JSONEq(t, string(data), string(encodingJSON)) require.JSONEq(t, string(data), string(dataA)) @@ -52,7 +51,7 @@ func encoding() *Encoding { }, }, Style: "form", - Explode: Ptr(true), + Explode: new(true), AllowReserved: true, } } @@ -74,17 +73,17 @@ func TestEncodingSerializationMethod(t *testing.T) { }, { name: "encoding with explode", - enc: &Encoding{Explode: Ptr(true)}, + enc: &Encoding{Explode: new(true)}, want: &SerializationMethod{Style: SerializationForm, Explode: true}, }, { name: "encoding with no explode", - enc: &Encoding{Explode: Ptr(false)}, + enc: &Encoding{Explode: new(false)}, want: &SerializationMethod{Style: SerializationForm, Explode: false}, }, { name: "encoding with style and explode ", - enc: &Encoding{Style: SerializationSpaceDelimited, Explode: Ptr(false)}, + enc: &Encoding{Style: SerializationSpaceDelimited, Explode: new(false)}, want: &SerializationMethod{Style: SerializationSpaceDelimited, Explode: false}, }, } diff --git a/openapi3/example_refs_test.go b/openapi3/example_refs_test.go index b2f36e3ea..5fe8e6955 100644 --- a/openapi3/example_refs_test.go +++ b/openapi3/example_refs_test.go @@ -3,8 +3,9 @@ package openapi3_test import ( "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestParameterExampleRef(t *testing.T) { diff --git a/openapi3/external_docs_test.go b/openapi3/external_docs_test.go index f2fb64f2e..b21b555c8 100644 --- a/openapi3/external_docs_test.go +++ b/openapi3/external_docs_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -31,7 +30,7 @@ func TestExternalDocs_Validate(t *testing.T) { for i := range tests { tt := tests[i] t.Run(tt.name, func(t *testing.T) { - err := tt.extDocs.Validate(context.Background()) + err := tt.extDocs.Validate(t.Context()) if tt.expectedErr != "" { require.EqualError(t, err, tt.expectedErr) } else { diff --git a/openapi3/helpers.go b/openapi3/helpers.go index 24c26a43a..ff24c94c5 100644 --- a/openapi3/helpers.go +++ b/openapi3/helpers.go @@ -31,39 +31,6 @@ func ValidateIdentifier(value string) error { return fmt.Errorf("identifier %q is not supported by OpenAPIv3 standard (charset: [%q])", value, identifierChars) } -// Ptr is a helper for defining OpenAPI schemas. -func Ptr[T any](value T) *T { - return &value -} - -// Float64Ptr is a helper for defining OpenAPI schemas. -// -// Deprecated: Use Ptr instead. -func Float64Ptr(value float64) *float64 { - return &value -} - -// BoolPtr is a helper for defining OpenAPI schemas. -// -// Deprecated: Use Ptr instead. -func BoolPtr(value bool) *bool { - return &value -} - -// Int64Ptr is a helper for defining OpenAPI schemas. -// -// Deprecated: Use Ptr instead. -func Int64Ptr(value int64) *int64 { - return &value -} - -// Uint64Ptr is a helper for defining OpenAPI schemas. -// -// Deprecated: Use Ptr instead. -func Uint64Ptr(value uint64) *uint64 { - return &value -} - // componentNames returns the map keys in a sorted slice. func componentNames[E any](s map[string]E) []string { out := make([]string, 0, len(s)) diff --git a/openapi3/info_test.go b/openapi3/info_test.go index f3aca8f03..5c813b996 100644 --- a/openapi3/info_test.go +++ b/openapi3/info_test.go @@ -3,8 +3,9 @@ package openapi3_test import ( "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestValidateInfo_SummaryIn30(t *testing.T) { diff --git a/openapi3/internalize_refs.go b/openapi3/internalize_refs.go index 918e26871..fe8b379eb 100644 --- a/openapi3/internalize_refs.go +++ b/openapi3/internalize_refs.go @@ -23,7 +23,7 @@ type RefNameResolver func(*T, ComponentRef) string // - Cutting the "#/components/" part. // - Cutting the file extensions (.yaml/.json) from documents. // - Trimming the common directory with the root spec. -// - Replace invalid characters with with underscores. +// - Replace invalid characters with underscores. // // This is an injective mapping over a "reasonable" amount of the possible openapi // spec domain space but is not perfect. There might be edge cases. @@ -34,7 +34,7 @@ func DefaultRefNameResolver(doc *T, ref ComponentRef) string { name := ref.RefPath() - // If refering to a component in the root spec, no need to internalize just use + // If referring to a component in the root spec, no need to internalize just use // the existing component. // XXX(percivalalb): since this function call is iterating over components behind the // scenes during an internalization call it actually starts interating over @@ -63,7 +63,7 @@ func DefaultRefNameResolver(doc *T, ref ComponentRef) string { filePath = "" } - // Remove the path extentions to make this JSON/YAML agnostic. + // Remove the path extensions to make this JSON/YAML agnostic. for ext := path.Ext(filePath); len(ext) > 0; ext = path.Ext(filePath) { filePath = strings.TrimSuffix(filePath, ext) } diff --git a/openapi3/internalize_refs_test.go b/openapi3/internalize_refs_test.go index 967ebca5e..a7ca69028 100644 --- a/openapi3/internalize_refs_test.go +++ b/openapi3/internalize_refs_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "os" "regexp" "testing" @@ -10,7 +9,7 @@ import ( ) func TestInternalizeRefs(t *testing.T) { - ctx := context.Background() + ctx := t.Context() regexpRef := regexp.MustCompile(`"\$ref":`) regexpRefInternal := regexp.MustCompile(`"\$ref":"#`) diff --git a/openapi3/issue230_test.go b/openapi3/issue230_test.go index 45a3ef1f2..1e63bb2f9 100644 --- a/openapi3/issue230_test.go +++ b/openapi3/issue230_test.go @@ -1,12 +1,12 @@ package openapi3_test import ( - "context" "encoding/json" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) // TestBackwardCompatibility_OpenAPI30 ensures that existing OpenAPI 3.0 functionality is not broken @@ -62,7 +62,7 @@ paths: require.Empty(t, doc.JSONSchemaDialect) // Validate - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.NoError(t, err) }) @@ -180,7 +180,7 @@ webhooks: require.Equal(t, "MIT", doc.Info.License.Identifier) // Validate - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.NoError(t, err) }) @@ -291,7 +291,7 @@ webhooks: Responses: openapi3.NewResponses( openapi3.WithStatus(200, &openapi3.ResponseRef{ Value: &openapi3.Response{ - Description: openapi3.Ptr("OK"), + Description: new("OK"), }, }), ), @@ -578,7 +578,7 @@ func TestPerformance(t *testing.T) { // Create a large schema properties := make(openapi3.Schemas) - for i := 0; i < 100; i++ { + for i := range 100 { properties[string(rune('a'+i%26))+string(rune('0'+i/26))] = &openapi3.SchemaRef{ Value: &openapi3.Schema{ Type: &openapi3.Types{"string"}, @@ -602,7 +602,7 @@ func TestPerformance(t *testing.T) { schema := &openapi3.Schema{Type: &openapi3.Types{"object"}} current := schema - for i := 0; i < 10; i++ { + for range 10 { current.Properties = openapi3.Schemas{ "nested": &openapi3.SchemaRef{ Value: &openapi3.Schema{ diff --git a/openapi3/issue341_test.go b/openapi3/issue341_test.go index 55f18e54d..770630ffb 100644 --- a/openapi3/issue341_test.go +++ b/openapi3/issue341_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -42,7 +41,7 @@ func TestIssue341(t *testing.T) { Schema.Value. Type) - doc.InternalizeRefs(context.Background(), nil) + doc.InternalizeRefs(t.Context(), nil) bs, err = doc.MarshalJSON() require.NoError(t, err) require.JSONEq(t, `{ diff --git a/openapi3/issue376_test.go b/openapi3/issue376_test.go index 362f08d69..13c28ea0e 100644 --- a/openapi3/issue376_test.go +++ b/openapi3/issue376_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "fmt" "testing" @@ -46,19 +45,19 @@ info: func TestExclusiveValuesOfValuesAdditionalProperties(t *testing.T) { schema := &Schema{ AdditionalProperties: AdditionalProperties{ - Has: Ptr(false), + Has: new(false), Schema: NewSchemaRef("", &Schema{}), }, } - err := schema.Validate(context.Background()) + err := schema.Validate(t.Context()) require.ErrorContains(t, err, ` to both `) schema = &Schema{ AdditionalProperties: AdditionalProperties{ - Has: Ptr(false), + Has: new(false), }, } - err = schema.Validate(context.Background()) + err = schema.Validate(t.Context()) require.NoError(t, err) schema = &Schema{ @@ -66,7 +65,7 @@ func TestExclusiveValuesOfValuesAdditionalProperties(t *testing.T) { Schema: NewSchemaRef("", &Schema{}), }, } - err = schema.Validate(context.Background()) + err = schema.Validate(t.Context()) require.NoError(t, err) } diff --git a/openapi3/issue638_test.go b/openapi3/issue638_test.go index 967195fd0..dd4261ff0 100644 --- a/openapi3/issue638_test.go +++ b/openapi3/issue638_test.go @@ -7,7 +7,7 @@ import ( ) func TestIssue638(t *testing.T) { - for i := 0; i < 50; i++ { + for range 50 { loader := NewLoader() loader.IsExternalRefsAllowed = true // This path affects the occurrence of the issue #638. diff --git a/openapi3/issue735_test.go b/openapi3/issue735_test.go index eb57ab896..199dabcd4 100644 --- a/openapi3/issue735_test.go +++ b/openapi3/issue735_test.go @@ -74,7 +74,7 @@ func TestIssue735(t *testing.T) { }, { name: "multiple of", - schema: &Schema{MultipleOf: Ptr(5.0)}, + schema: &Schema{MultipleOf: new(5.0)}, value: 42, }, { @@ -142,7 +142,7 @@ func TestIssue735(t *testing.T) { { name: "additional properties false", schema: &Schema{AdditionalProperties: AdditionalProperties{ - Has: Ptr(false), + Has: new(false), }}, value: map[string]any{"foo": 42}, extraNotContains: []any{42}, @@ -188,40 +188,40 @@ func TestIssue735(t *testing.T) { { name: "one of (matches more then one)", schema: NewOneOfSchema( - &Schema{MultipleOf: Ptr(6.0)}, - &Schema{MultipleOf: Ptr(7.0)}, + &Schema{MultipleOf: new(6.0)}, + &Schema{MultipleOf: new(7.0)}, ), value: 42, }, { name: "one of (no matches)", schema: NewOneOfSchema( - &Schema{MultipleOf: Ptr(5.0)}, - &Schema{MultipleOf: Ptr(10.0)}, + &Schema{MultipleOf: new(5.0)}, + &Schema{MultipleOf: new(10.0)}, ), value: 42, }, { name: "any of", schema: NewAnyOfSchema( - &Schema{MultipleOf: Ptr(5.0)}, - &Schema{MultipleOf: Ptr(10.0)}, + &Schema{MultipleOf: new(5.0)}, + &Schema{MultipleOf: new(10.0)}, ), value: 42, }, { name: "all of (match some)", schema: NewAllOfSchema( - &Schema{MultipleOf: Ptr(6.0)}, - &Schema{MultipleOf: Ptr(5.0)}, + &Schema{MultipleOf: new(6.0)}, + &Schema{MultipleOf: new(5.0)}, ), value: 42, }, { name: "all of (no match)", schema: NewAllOfSchema( - &Schema{MultipleOf: Ptr(10.0)}, - &Schema{MultipleOf: Ptr(5.0)}, + &Schema{MultipleOf: new(10.0)}, + &Schema{MultipleOf: new(5.0)}, ), value: 42, }, diff --git a/openapi3/issue741_test.go b/openapi3/issue741_test.go index aad522023..3d5fbfc3c 100644 --- a/openapi3/issue741_test.go +++ b/openapi3/issue741_test.go @@ -14,30 +14,26 @@ func TestIssue741(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) body := `{"openapi":"3.0.0","info":{"title":"MyAPI","version":"0.1","description":"An API"},"paths":{},"components":{"schemas":{"Foo":{"type":"string"}}}}` - _, err := w.Write([]byte(body)) - if err != nil { + if _, err := w.Write([]byte(body)); err != nil { panic(err) } })) defer ts.Close() - rootSpec := []byte(fmt.Sprintf( + rootSpec := fmt.Appendf(nil, `{"openapi":"3.0.0","info":{"title":"MyAPI","version":"0.1","description":"An API"},"paths":{},"components":{"schemas":{"Bar1":{"$ref":"%s#/components/schemas/Foo"}}}}`, ts.URL, - )) + ) - wg := &sync.WaitGroup{} - n := 10 - for i := 0; i < n; i++ { - wg.Add(1) - go func() { - defer wg.Done() + var wg sync.WaitGroup + for range 10 { + wg.Go(func() { loader := NewLoader() loader.IsExternalRefsAllowed = true doc, err := loader.LoadFromData(rootSpec) require.NoError(t, err) require.NotNil(t, doc) - }() + }) } wg.Wait() } diff --git a/openapi3/issue767_test.go b/openapi3/issue767_test.go index 04fd9d03f..e889c069e 100644 --- a/openapi3/issue767_test.go +++ b/openapi3/issue767_test.go @@ -11,7 +11,7 @@ import ( func TestIssue767(t *testing.T) { t.Parallel() - tests := [...]struct { + tests := []struct { name string schema *openapi3.Schema value map[string]any diff --git a/openapi3/loader.go b/openapi3/loader.go index 3324792ee..5df84d750 100644 --- a/openapi3/loader.go +++ b/openapi3/loader.go @@ -566,7 +566,7 @@ func drillIntoField(cursor any, fieldName string) (any, error) { case reflect.Struct: hasFields := false - for i := 0; i < val.NumField(); i++ { + for i := range val.NumField() { hasFields = true if yamlTag := val.Type().Field(i).Tag.Get("yaml"); yamlTag != "-" { if tagName := strings.Split(yamlTag, ",")[0]; tagName != "" { diff --git a/openapi3/loader_31_conditional_test.go b/openapi3/loader_31_conditional_test.go index 44c912377..29b89e950 100644 --- a/openapi3/loader_31_conditional_test.go +++ b/openapi3/loader_31_conditional_test.go @@ -3,8 +3,9 @@ package openapi3_test import ( "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestResolveConditionalSchemaRefs(t *testing.T) { diff --git a/openapi3/loader_31_schema_refs_test.go b/openapi3/loader_31_schema_refs_test.go index 4fa65bbdf..c720a2f23 100644 --- a/openapi3/loader_31_schema_refs_test.go +++ b/openapi3/loader_31_schema_refs_test.go @@ -5,8 +5,9 @@ import ( "strings" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) // TestOAS31_RefSiblingKeyword verifies that sibling keywords alongside $ref are honoured diff --git a/openapi3/loader_outside_refs_test.go b/openapi3/loader_outside_refs_test.go index 7300c2c50..be30a4fbc 100644 --- a/openapi3/loader_outside_refs_test.go +++ b/openapi3/loader_outside_refs_test.go @@ -56,5 +56,10 @@ components: loader := NewLoader() loader.IsExternalRefsAllowed = true - loader.LoadFromData([]byte(spec)) + doc, err := loader.LoadFromData([]byte(spec)) + require.NoError(t, err) + require.NotNil(t, doc) + + err = doc.Validate(loader.Context, AllowExtraSiblingFields("description")) + require.NoError(t, err) } diff --git a/openapi3/loader_paths_test.go b/openapi3/loader_paths_test.go index f7edc7374..d46af218e 100644 --- a/openapi3/loader_paths_test.go +++ b/openapi3/loader_paths_test.go @@ -28,6 +28,7 @@ paths: loader := NewLoader() doc, err := loader.LoadFromData([]byte(strings.Replace(spec, "PATH", path, 1))) require.NoError(t, err) + err = doc.Validate(loader.Context) if expectedErr != "" { require.EqualError(t, err, expectedErr) diff --git a/openapi3/loader_read_from_uri_func_test.go b/openapi3/loader_read_from_uri_func_test.go index 50f3e38f5..7feb1287c 100644 --- a/openapi3/loader_read_from_uri_func_test.go +++ b/openapi3/loader_read_from_uri_func_test.go @@ -45,7 +45,8 @@ func TestLoaderReadFromURIFunc(t *testing.T) { doc, err := loader.LoadFromFile("recursiveRef/openapi.yml") require.NoError(t, err) require.NotNil(t, doc) - require.NoError(t, doc.Validate(loader.Context)) + err = doc.Validate(loader.Context) + require.NoError(t, err) require.Equal(t, "bar", doc. Paths.Value("/foo"). Get. diff --git a/openapi3/loader_relative_refs_test.go b/openapi3/loader_relative_refs_test.go index 05f9d0e4c..51a5db76c 100644 --- a/openapi3/loader_relative_refs_test.go +++ b/openapi3/loader_relative_refs_test.go @@ -198,7 +198,7 @@ func TestLoadFromDataWithExternalRef(t *testing.T) { for _, td := range refTestDataEntries { t.Logf("testcase %q", td.name) - spec := []byte(fmt.Sprintf(td.contentTemplate, "components.openapi.json")) + spec := fmt.Appendf(nil, td.contentTemplate, "components.openapi.json") loader := NewLoader() loader.IsExternalRefsAllowed = true doc, err := loader.LoadFromDataWithPath(spec, &url.URL{Path: "testdata/testfilename.openapi.json"}) @@ -211,7 +211,7 @@ func TestLoadFromDataWithExternalRefResponseError(t *testing.T) { for _, td := range refTestDataEntriesResponseError { t.Logf("testcase %q", td.name) - spec := []byte(fmt.Sprintf(td.contentTemplate, "components.openapi.json")) + spec := fmt.Appendf(nil, td.contentTemplate, "components.openapi.json") loader := NewLoader() loader.IsExternalRefsAllowed = true doc, err := loader.LoadFromDataWithPath(spec, &url.URL{Path: "testdata/testfilename.openapi.json"}) @@ -224,7 +224,7 @@ func TestLoadFromDataWithExternalNestedRef(t *testing.T) { for _, td := range refTestDataEntries { t.Logf("testcase %q", td.name) - spec := []byte(fmt.Sprintf(td.contentTemplate, "nesteddir/nestedcomponents.openapi.json")) + spec := fmt.Appendf(nil, td.contentTemplate, "nesteddir/nestedcomponents.openapi.json") loader := NewLoader() loader.IsExternalRefsAllowed = true doc, err := loader.LoadFromDataWithPath(spec, &url.URL{Path: "testdata/testfilename.openapi.json"}) diff --git a/openapi3/media_type_test.go b/openapi3/media_type_test.go index 099c4b667..c1d4609c1 100644 --- a/openapi3/media_type_test.go +++ b/openapi3/media_type_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "encoding/json" "testing" @@ -15,17 +14,17 @@ func TestMediaTypeJSON(t *testing.T) { require.NotEmpty(t, data) t.Log("Unmarshal *openapi3.MediaType from JSON") - docA := &MediaType{} - err = json.Unmarshal(mediaTypeJSON, &docA) + mt := &MediaType{} + err = json.Unmarshal(mediaTypeJSON, &mt) require.NoError(t, err) require.NotEmpty(t, data) t.Log("Validate *openapi3.MediaType") - err = docA.Validate(context.Background()) + err = mt.Validate(t.Context()) require.NoError(t, err) t.Log("Ensure representations match") - dataA, err := json.Marshal(docA) + dataA, err := json.Marshal(mt) require.NoError(t, err) require.JSONEq(t, string(data), string(mediaTypeJSON)) require.JSONEq(t, string(data), string(dataA)) diff --git a/openapi3/openapi3_test.go b/openapi3/openapi3_test.go index 587d59d5e..3a0b80c59 100644 --- a/openapi3/openapi3_test.go +++ b/openapi3/openapi3_test.go @@ -1,16 +1,16 @@ package openapi3_test import ( - "context" "encoding/json" "fmt" "strings" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/oasdiff/yaml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestRefsJSON(t *testing.T) { @@ -435,7 +435,7 @@ components: err := yaml.Unmarshal([]byte(tt.spec), &doc) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) if tt.expectedErr != "" { require.EqualError(t, err, tt.expectedErr) } else { diff --git a/openapi3/openapi3_version_test.go b/openapi3/openapi3_version_test.go index c3b1da3ab..ecb219e33 100644 --- a/openapi3/openapi3_version_test.go +++ b/openapi3/openapi3_version_test.go @@ -1,12 +1,12 @@ package openapi3_test import ( - "context" "encoding/json" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestWebhooksField(t *testing.T) { @@ -25,7 +25,7 @@ func TestWebhooksField(t *testing.T) { Responses: openapi3.NewResponses( openapi3.WithStatus(200, &openapi3.ResponseRef{ Value: &openapi3.Response{ - Description: openapi3.Ptr("Success"), + Description: new("Success"), }, }), ), @@ -107,7 +107,7 @@ func TestWebhooksField(t *testing.T) { Responses: openapi3.NewResponses( openapi3.WithStatus(200, &openapi3.ResponseRef{ Value: &openapi3.Response{ - Description: openapi3.Ptr("Success"), + Description: new("Success"), }, }), ), @@ -117,7 +117,7 @@ func TestWebhooksField(t *testing.T) { } // Should validate successfully - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) }) @@ -134,7 +134,7 @@ func TestWebhooksField(t *testing.T) { }, } - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.Error(t, err) require.ErrorContains(t, err, "webhook") require.ErrorContains(t, err, "invalidWebhook") @@ -199,7 +199,7 @@ func TestVersionBasedBehavior(t *testing.T) { Responses: openapi3.NewResponses( openapi3.WithStatus(200, &openapi3.ResponseRef{ Value: &openapi3.Response{ - Description: openapi3.Ptr("OK"), + Description: new("OK"), }, }), ), @@ -242,7 +242,7 @@ func TestMigrationScenario(t *testing.T) { Responses: openapi3.NewResponses( openapi3.WithStatus(200, &openapi3.ResponseRef{ Value: &openapi3.Response{ - Description: openapi3.Ptr("Processed"), + Description: new("Processed"), }, }), ), @@ -254,7 +254,7 @@ func TestMigrationScenario(t *testing.T) { require.NotNil(t, doc.Webhooks) // Validate the upgraded document - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) }) } diff --git a/openapi3/operation_test.go b/openapi3/operation_test.go index 4c3a7bde5..a17c029c3 100644 --- a/openapi3/operation_test.go +++ b/openapi3/operation_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "errors" "testing" @@ -63,7 +62,7 @@ func TestOperationValidation(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := context.Background() + c := t.Context() validationErr := test.input.Validate(c) require.Equal(t, test.expectedError, validationErr, "expected errors (or lack of) to match") diff --git a/openapi3/origin.go b/openapi3/origin.go index 432ecabdf..1403bd881 100644 --- a/openapi3/origin.go +++ b/openapi3/origin.go @@ -162,7 +162,7 @@ func applyOriginsToStruct(val reflect.Value, ptr reflect.Value, tree *yaml.Origi } // Recurse into exported struct fields using json tags - for i := 0; i < typ.NumField(); i++ { + for i := range typ.NumField() { sf := typ.Field(i) if !sf.IsExported() { continue diff --git a/openapi3/origin_load_test.go b/openapi3/origin_load_test.go index 51159186c..438cc2dd9 100644 --- a/openapi3/origin_load_test.go +++ b/openapi3/origin_load_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -48,7 +47,7 @@ func TestOrigin_LoadAllTestdata(t *testing.T) { loader := NewLoader() loader.IncludeOrigin = true loader.IsExternalRefsAllowed = tc.externalRefs - loader.Context = context.Background() + loader.Context = t.Context() _, err := loader.LoadFromFile(tc.file) require.NoError(t, err) diff --git a/openapi3/origin_test.go b/openapi3/origin_test.go index e6ed20421..3f63976df 100644 --- a/openapi3/origin_test.go +++ b/openapi3/origin_test.go @@ -1,11 +1,11 @@ package openapi3_test import ( - "context" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) const originKey = "__origin__" @@ -14,7 +14,7 @@ func TestOrigin_Info(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/simple.yaml") require.NoError(t, err) @@ -52,7 +52,7 @@ func TestOrigin_Paths(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/simple.yaml") require.NoError(t, err) @@ -94,7 +94,7 @@ func TestOrigin_RequestBody(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/request_body.yaml") require.NoError(t, err) @@ -125,7 +125,7 @@ func TestOrigin_Responses(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/simple.yaml") require.NoError(t, err) @@ -175,7 +175,7 @@ func TestOrigin_Parameters(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/parameters.yaml") require.NoError(t, err) @@ -214,7 +214,7 @@ func TestOrigin_SchemaInAdditionalProperties(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/additional_properties.yaml") require.NoError(t, err) @@ -246,7 +246,7 @@ func TestOrigin_ExternalDocs(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/external_docs.yaml") require.NoError(t, err) @@ -286,7 +286,7 @@ func TestOrigin_Security(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/security.yaml") require.NoError(t, err) @@ -344,7 +344,7 @@ func TestOrigin_Example(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/example.yaml") require.NoError(t, err) @@ -379,7 +379,7 @@ func TestOrigin_XML(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/xml.yaml") require.NoError(t, err) @@ -578,7 +578,7 @@ func TestOrigin_WithExternalRef(t *testing.T) { loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/external.yaml") require.NoError(t, err) @@ -622,7 +622,7 @@ func TestOrigin_WithExternalRefRootOrigin(t *testing.T) { loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.IncludeOrigin = true - loader.Context = context.Background() + loader.Context = t.Context() doc, err := loader.LoadFromFile("testdata/origin/external.yaml") require.NoError(t, err) diff --git a/openapi3/parameter_issue223_test.go b/openapi3/parameter_issue223_test.go index 82660885d..c94de4c26 100644 --- a/openapi3/parameter_issue223_test.go +++ b/openapi3/parameter_issue223_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -112,6 +111,6 @@ components: loader := NewLoader() doc, err := loader.LoadFromData(spec) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.EqualError(t, err, `invalid paths: operation GET /pets/{petId} must define exactly all path parameters (missing: [petId])`) } diff --git a/openapi3/parameter_issue834_test.go b/openapi3/parameter_issue834_test.go index 1a1532168..52d100a0d 100644 --- a/openapi3/parameter_issue834_test.go +++ b/openapi3/parameter_issue834_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -37,7 +36,7 @@ paths: loader := NewLoader() doc, err := loader.LoadFromData(spec) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.EqualError(t, err, `invalid paths: invalid path /pets: parameter can't have 'in' value "invalid"`) } @@ -76,7 +75,7 @@ paths: loader := NewLoader() doc, err := loader.LoadFromData(spec) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.EqualError(t, err, `invalid paths: invalid path /pets: parameter "test" content is invalid: parameter content must only contain one entry`) } @@ -109,6 +108,6 @@ paths: loader := NewLoader() doc, err := loader.LoadFromData(spec) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.EqualError(t, err, `invalid paths: invalid path /pets: parameter "test" schema is invalid: parameter must contain exactly one of content and schema`) } diff --git a/openapi3/paths.go b/openapi3/paths.go index 2a58d9226..8082e3770 100644 --- a/openapi3/paths.go +++ b/openapi3/paths.go @@ -93,14 +93,10 @@ func (paths *Paths) Validate(ctx context.Context, opts ...ValidationOption) erro } } for _, name := range componentNames(varsInPath) { - got := false if slices.Contains(definedParams, name) { - got = true break } - if !got { - missing[name] = struct{}{} - } + missing[name] = struct{}{} } if len(missing) != 0 { missings := componentNames(missing) diff --git a/openapi3/paths_test.go b/openapi3/paths_test.go index ad7a921b9..7987d2ab1 100644 --- a/openapi3/paths_test.go +++ b/openapi3/paths_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -85,7 +84,7 @@ paths: doc, err := loader.LoadFromData([]byte(tt.spec[1:])) require.NoError(t, err) - err = doc.Paths.Validate(context.Background()) + err = doc.Paths.Validate(t.Context()) if tt.wantErr == "" { require.NoError(t, err) return diff --git a/openapi3/race_test.go b/openapi3/race_test.go index 405942520..56e2a7ae8 100644 --- a/openapi3/race_test.go +++ b/openapi3/race_test.go @@ -1,7 +1,6 @@ package openapi3_test import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -12,7 +11,7 @@ import ( func TestRaceyPatternSchemaValidateHindersIt(t *testing.T) { schema := openapi3.NewStringSchema().WithPattern("^test|for|race|condition$") - err := schema.Validate(context.Background()) + err := schema.Validate(t.Context()) require.NoError(t, err) visit := func() { @@ -27,7 +26,7 @@ func TestRaceyPatternSchemaValidateHindersIt(t *testing.T) { func TestRaceyPatternSchemaForIssue775(t *testing.T) { schema := openapi3.NewStringSchema().WithPattern("^test|for|race|condition$") - // err := schema.Validate(context.Background()) + // err := schema.Validate(t.Context()) // require.NoError(t, err) visit := func() { diff --git a/openapi3/refs_test.go b/openapi3/refs_test.go index 89ad64e1f..f1bf3884b 100644 --- a/openapi3/refs_test.go +++ b/openapi3/refs_test.go @@ -2,7 +2,6 @@ package openapi3 import ( - "context" "encoding/json" "testing" @@ -26,13 +25,13 @@ func TestCallbackRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -72,13 +71,13 @@ func TestExampleRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -118,13 +117,13 @@ func TestHeaderRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -156,13 +155,13 @@ func TestLinkRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -202,13 +201,13 @@ func TestParameterRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -248,13 +247,13 @@ func TestRequestBodyRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -294,13 +293,13 @@ func TestResponseRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -340,13 +339,13 @@ func TestSchemaRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON @@ -386,13 +385,13 @@ func TestSecuritySchemeRef_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON diff --git a/openapi3/refs_test.tmpl b/openapi3/refs_test.tmpl index a11e1769d..6ddacb6bb 100644 --- a/openapi3/refs_test.tmpl +++ b/openapi3/refs_test.tmpl @@ -2,7 +2,6 @@ package {{ .Package }} import ( - "context" "encoding/json" "testing" @@ -26,13 +25,13 @@ func Test{{ $type.Name }}Ref_Extensions(t *testing.T) { assert.Nil(t, ref.Extensions["something"]) // validation - err = ref.Validate(context.Background()) + err = ref.Validate(t.Context()) require.EqualError(t, err, "extra sibling fields: [something]") - err = ref.Validate(context.Background(), ProhibitExtensionsWithRef()) + err = ref.Validate(t.Context(), ProhibitExtensionsWithRef()) require.EqualError(t, err, "extra sibling fields: [something x-order]") - err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) + err = ref.Validate(t.Context(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined // Verify round trip JSON diff --git a/openapi3/response_issue224_test.go b/openapi3/response_issue224_test.go index 265f88a29..185291d89 100644 --- a/openapi3/response_issue224_test.go +++ b/openapi3/response_issue224_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -460,6 +459,6 @@ func TestEmptyResponsesAreInvalid(t *testing.T) { require.Equal(t, "See AsyncAPI example", doc.ExternalDocs.Description) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.EqualError(t, err, `invalid paths: invalid path /pet: invalid operation POST: the responses object MUST contain at least one response code`) } diff --git a/openapi3/schema.go b/openapi3/schema.go index 2433695a4..75def448a 100644 --- a/openapi3/schema.go +++ b/openapi3/schema.go @@ -10,6 +10,7 @@ import ( "math" "math/big" "reflect" + "slices" "strconv" "strings" "sync" @@ -229,13 +230,7 @@ func (pTypes *Types) Includes(typ string) bool { if pTypes == nil { return false } - types := *pTypes - for _, candidate := range types { - if candidate == typ { - return true - } - } - return false + return slices.Contains(*pTypes, typ) } // Permits returns true if the given type is permitted. @@ -1225,12 +1220,10 @@ func (schema *Schema) WithProperty(name string, propertySchema *Schema) *Schema } func (schema *Schema) WithPropertyRef(name string, ref *SchemaRef) *Schema { - properties := schema.Properties - if properties == nil { - properties = make(Schemas) - schema.Properties = properties + if schema.Properties == nil { + schema.Properties = make(Schemas) } - properties[name] = ref + schema.Properties[name] = ref return schema } @@ -1263,12 +1256,12 @@ func (schema *Schema) WithMaxProperties(i int64) *Schema { } func (schema *Schema) WithAnyAdditionalProperties() *Schema { - schema.AdditionalProperties = AdditionalProperties{Has: Ptr(true)} + schema.AdditionalProperties = AdditionalProperties{Has: new(true)} return schema } func (schema *Schema) WithoutAdditionalProperties() *Schema { - schema.AdditionalProperties = AdditionalProperties{Has: Ptr(false)} + schema.AdditionalProperties = AdditionalProperties{Has: new(false)} return schema } @@ -1410,13 +1403,12 @@ func (schema *Schema) Validate(ctx context.Context, opts ...ValidationOption) er // returns the updated stack and an error if Schema does not comply with the OpenAPI spec. func (schema *Schema) validate(ctx context.Context, stack []*Schema) ([]*Schema, error) { + if slices.Contains(stack, schema) { + return stack, nil + } + validationOpts := getValidationOptions(ctx) - for _, existing := range stack { - if existing == schema { - return stack, nil - } - } stack = append(stack, schema) if schema.ReadOnly && schema.WriteOnly { @@ -2086,7 +2078,7 @@ func (schema *Schema) visitEnumOperation(settings *schemaValidationSettings, val Value: value, Schema: schema, SchemaField: "enum", - Reason: fmt.Sprintf("value is not one of the allowed values %s", string(allowedValues)), + Reason: "value is not one of the allowed values " + string(allowedValues), customizeMessageError: settings.customizeMessageError, } } @@ -2119,7 +2111,7 @@ func (schema *Schema) visitConstOperation(settings *schemaValidationSettings, va Value: value, Schema: schema, SchemaField: "const", - Reason: fmt.Sprintf("value must be %s", string(constVal)), + Reason: "value must be " + string(constVal), customizeMessageError: settings.customizeMessageError, } } diff --git a/openapi3/schema_allof_test.go b/openapi3/schema_allof_test.go index b241cb756..d03926483 100644 --- a/openapi3/schema_allof_test.go +++ b/openapi3/schema_allof_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "encoding/json" "errors" "testing" @@ -56,7 +55,7 @@ func TestAllOfErrorPreserved(t *testing.T) { s := NewSchema() err := s.UnmarshalJSON([]byte(schema)) require.NoError(t, err) - err = s.Validate(context.Background()) + err = s.Validate(t.Context()) require.NoError(t, err) obj := make(map[string]any) diff --git a/openapi3/schema_const_test.go b/openapi3/schema_const_test.go index 1bbf420a2..1867e7475 100644 --- a/openapi3/schema_const_test.go +++ b/openapi3/schema_const_test.go @@ -3,8 +3,9 @@ package openapi3_test import ( "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestSchemaConst_BuiltInValidator(t *testing.T) { diff --git a/openapi3/schema_formats_test.go b/openapi3/schema_formats_test.go index 7ae3c5035..682ac6f27 100644 --- a/openapi3/schema_formats_test.go +++ b/openapi3/schema_formats_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "errors" "fmt" "testing" @@ -19,7 +18,7 @@ func TestIssue430(t *testing.T) { delete(SchemaStringFormats, "ipv4") delete(SchemaStringFormats, "ipv6") - err := schema.Validate(context.Background()) + err := schema.Validate(t.Context()) require.NoError(t, err) data := map[string]bool{ diff --git a/openapi3/schema_if_then_else_test.go b/openapi3/schema_if_then_else_test.go index 372a27ebe..d2a6db6a1 100644 --- a/openapi3/schema_if_then_else_test.go +++ b/openapi3/schema_if_then_else_test.go @@ -1,11 +1,11 @@ package openapi3_test import ( - "context" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestSchemaIfThenElse_BuiltInValidator(t *testing.T) { @@ -176,7 +176,7 @@ func TestSchemaIfThenElse_Validate(t *testing.T) { schema := &openapi3.Schema{ If: &openapi3.SchemaRef{Ref: "#/components/schemas/Missing"}, } - err := schema.Validate(context.Background(), openapi3.IsOpenAPI31OrLater()) + err := schema.Validate(t.Context(), openapi3.IsOpenAPI31OrLater()) require.Error(t, err) require.ErrorContains(t, err, "unresolved ref") }) @@ -185,7 +185,7 @@ func TestSchemaIfThenElse_Validate(t *testing.T) { schema := &openapi3.Schema{ Then: &openapi3.SchemaRef{Ref: "#/components/schemas/Missing"}, } - err := schema.Validate(context.Background(), openapi3.IsOpenAPI31OrLater()) + err := schema.Validate(t.Context(), openapi3.IsOpenAPI31OrLater()) require.Error(t, err) require.ErrorContains(t, err, "unresolved ref") }) @@ -194,7 +194,7 @@ func TestSchemaIfThenElse_Validate(t *testing.T) { schema := &openapi3.Schema{ Else: &openapi3.SchemaRef{Ref: "#/components/schemas/Missing"}, } - err := schema.Validate(context.Background(), openapi3.IsOpenAPI31OrLater()) + err := schema.Validate(t.Context(), openapi3.IsOpenAPI31OrLater()) require.Error(t, err) require.ErrorContains(t, err, "unresolved ref") }) @@ -205,7 +205,7 @@ func TestSchemaIfThenElse_Validate(t *testing.T) { Then: &openapi3.SchemaRef{Value: &openapi3.Schema{MinLength: 1}}, Else: &openapi3.SchemaRef{Value: &openapi3.Schema{Type: &openapi3.Types{"number"}}}, } - err := schema.Validate(context.Background(), openapi3.IsOpenAPI31OrLater()) + err := schema.Validate(t.Context(), openapi3.IsOpenAPI31OrLater()) require.NoError(t, err) }) } diff --git a/openapi3/schema_issue940_test.go b/openapi3/schema_issue940_test.go index 792199489..965ea1037 100644 --- a/openapi3/schema_issue940_test.go +++ b/openapi3/schema_issue940_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "encoding/json" "errors" "testing" @@ -43,7 +42,7 @@ func TestOneOfErrorPreserved(t *testing.T) { s := NewSchema() err := s.UnmarshalJSON([]byte(schema)) require.NoError(t, err) - err = s.Validate(context.Background()) + err = s.Validate(t.Context()) require.NoError(t, err) obj := make(map[string]any) diff --git a/openapi3/schema_jsonschema_validator.go b/openapi3/schema_jsonschema_validator.go index 7b3443d55..fc92a596b 100644 --- a/openapi3/schema_jsonschema_validator.go +++ b/openapi3/schema_jsonschema_validator.go @@ -152,9 +152,8 @@ func (v *jsonSchemaValidator) validate(value any) error { // convertJSONSchemaError converts a jsonschema validation error to OpenAPI SchemaError format func convertJSONSchemaError(err error) error { - var validationErr *jsonschema.ValidationError - if errors.As(err, &validationErr) { - return formatValidationError(validationErr, "") + if err, ok := errors.AsType[*jsonschema.ValidationError](err); ok { + return formatValidationError(err, "") } return err } @@ -172,7 +171,7 @@ func formatValidationError(verr *jsonschema.ValidationError, parentPath string) // Build error message using the Error() method var msg strings.Builder if path != "" { - msg.WriteString(fmt.Sprintf(`error at "%s": `, path)) + fmt.Fprintf(&msg, `error at "%s": `, path) } msg.WriteString(verr.Error()) diff --git a/openapi3/schema_jsonschema_validator_test.go b/openapi3/schema_jsonschema_validator_test.go index 1a7c3bf42..d79a2fb4b 100644 --- a/openapi3/schema_jsonschema_validator_test.go +++ b/openapi3/schema_jsonschema_validator_test.go @@ -3,8 +3,9 @@ package openapi3_test import ( "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestJSONSchema2020Validator_Basic(t *testing.T) { diff --git a/openapi3/schema_oneOf_test.go b/openapi3/schema_oneOf_test.go index 336c2843c..c3f74f121 100644 --- a/openapi3/schema_oneOf_test.go +++ b/openapi3/schema_oneOf_test.go @@ -212,11 +212,8 @@ components: }, }, }) - require.ErrorContains(t, err, `Error at "/first/second/third"`) - var sErr *SchemaError - require.ErrorAs(t, err, &sErr) require.Equal(t, []string{"first", "second", "third"}, sErr.JSONPointer()) } diff --git a/openapi3/schema_pattern_test.go b/openapi3/schema_pattern_test.go index 988adfa45..9417871ec 100644 --- a/openapi3/schema_pattern_test.go +++ b/openapi3/schema_pattern_test.go @@ -8,7 +8,7 @@ import ( ) func TestPattern(t *testing.T) { - _, err := regexp.Compile("^[a-zA-Z\\u0080-\\u024F\\s\\/\\-\\)\\(\\`\\.\\\"\\']+$") + _, err := regexp.Compile("^[a-zA-Z\\u0080-\\u024F\\s\\/\\-\\)\\(\\`\\.\\\"\\']+$") //nolint:staticcheck require.EqualError(t, err, "error parsing regexp: invalid escape sequence: `\\u`") _, err = regexp.Compile(`^[a-zA-Z\x{0080}-\x{024F}]+$`) diff --git a/openapi3/schema_test.go b/openapi3/schema_test.go index ef35dc2fa..b36541b8d 100644 --- a/openapi3/schema_test.go +++ b/openapi3/schema_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "encoding/base64" "encoding/json" "fmt" @@ -543,7 +542,7 @@ var schemaExamples = []schemaExample{ Schema: &Schema{ Type: &Types{"array"}, MinItems: 2, - MaxItems: Ptr[uint64](3), + MaxItems: new(uint64(3)), UniqueItems: true, Items: NewFloat64Schema().NewRef(), }, @@ -873,7 +872,7 @@ var schemaExamples = []schemaExample{ Title: "OBJECT", Schema: &Schema{ Type: &Types{"object"}, - MaxProps: Ptr[uint64](2), + MaxProps: new(uint64(2)), Properties: Schemas{ "numberProperty": NewFloat64Schema().NewRef(), }, @@ -945,7 +944,7 @@ var schemaExamples = []schemaExample{ { Schema: &Schema{ Type: &Types{"object"}, - AdditionalProperties: AdditionalProperties{Has: Ptr(true)}, + AdditionalProperties: AdditionalProperties{Has: new(true)}, }, Serialization: map[string]any{ "type": "object", @@ -1130,21 +1129,21 @@ type schemaTypeExample struct { func TestTypes(t *testing.T) { for _, example := range typeExamples { - t.Run(example.Title, testType(t, example)) + t.Run(example.Title, testType(example)) } } -func testType(t *testing.T, example schemaTypeExample) func(*testing.T) { +func testType(example schemaTypeExample) func(*testing.T) { return func(t *testing.T) { baseSchema := example.Schema for _, typ := range example.AllValid { schema := baseSchema.WithFormat(typ) - err := schema.Validate(context.Background()) + err := schema.Validate(t.Context()) require.NoError(t, err) } for _, typ := range example.AllInvalid { schema := baseSchema.WithFormat(typ) - ctx := WithValidationOptions(context.Background(), EnableSchemaFormatValidation()) + ctx := WithValidationOptions(t.Context(), EnableSchemaFormatValidation()) err := schema.Validate(ctx) require.Error(t, err) } @@ -1199,11 +1198,11 @@ var typeExamples = []schemaTypeExample{ func TestSchemaErrors(t *testing.T) { for _, example := range schemaErrorExamples { - t.Run(example.Title, testSchemaError(t, example)) + t.Run(example.Title, testSchemaError(example)) } } -func testSchemaError(t *testing.T, example schemaErrorExample) func(*testing.T) { +func testSchemaError(example schemaErrorExample) func(*testing.T) { return func(t *testing.T) { msg := example.Error.Error() require.True(t, strings.Contains(msg, example.Want)) @@ -1251,11 +1250,11 @@ type schemaMultiErrorExample struct { func TestSchemasMultiError(t *testing.T) { for _, example := range schemaMultiErrorExamples { - t.Run(example.Title, testSchemaMultiError(t, example)) + t.Run(example.Title, testSchemaMultiError(example)) } } -func testSchemaMultiError(t *testing.T, example schemaMultiErrorExample) func(*testing.T) { +func testSchemaMultiError(example schemaMultiErrorExample) func(*testing.T) { return func(t *testing.T) { schema := example.Schema for validateFuncIndex, validateFunc := range validateSchemaFuncs { @@ -1434,7 +1433,7 @@ func TestValidationFailsOnInvalidPattern(t *testing.T) { Type: &Types{"string"}, } - err := schema.Validate(context.Background()) + err := schema.Validate(t.Context()) require.Error(t, err) } @@ -1452,7 +1451,7 @@ enum: err := yaml.Unmarshal(data, &schema) require.NoError(t, err) - err = schema.Validate(context.Background()) + err = schema.Validate(t.Context()) require.NoError(t, err) err = schema.VisitJSON(42) diff --git a/openapi3/schema_types_test.go b/openapi3/schema_types_test.go index 6fd3bc54d..a7e3e35a6 100644 --- a/openapi3/schema_types_test.go +++ b/openapi3/schema_types_test.go @@ -4,8 +4,9 @@ import ( "encoding/json" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestTypes_HelperMethods(t *testing.T) { diff --git a/openapi3/schema_validate_31_test.go b/openapi3/schema_validate_31_test.go index bf91a6d2d..1d1983f20 100644 --- a/openapi3/schema_validate_31_test.go +++ b/openapi3/schema_validate_31_test.go @@ -1,15 +1,15 @@ package openapi3_test import ( - "context" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) func TestSchemaValidate31SubSchemas(t *testing.T) { - ctx := openapi3.WithValidationOptions(context.Background(), openapi3.IsOpenAPI31OrLater()) + ctx := openapi3.WithValidationOptions(t.Context(), openapi3.IsOpenAPI31OrLater()) // Helper: a schema with an invalid nested schema (pattern with bad regex) invalidSchema := &openapi3.Schema{ diff --git a/openapi3/security_requirements.go b/openapi3/security_requirements.go index d5310d87a..36b6401b1 100644 --- a/openapi3/security_requirements.go +++ b/openapi3/security_requirements.go @@ -45,7 +45,7 @@ func (security SecurityRequirement) Authenticate(provider string, scopes ...stri // Validate returns an error if SecurityRequirement does not comply with the OpenAPI spec. func (security *SecurityRequirement) Validate(ctx context.Context, opts ...ValidationOption) error { - ctx = WithValidationOptions(ctx, opts...) + // ctx = WithValidationOptions(ctx, opts...) return nil } diff --git a/openapi3/security_scheme.go b/openapi3/security_scheme.go index 0afc7920b..1fb166232 100644 --- a/openapi3/security_scheme.go +++ b/openapi3/security_scheme.go @@ -7,6 +7,7 @@ import ( "fmt" "maps" "net/url" + "slices" ) // SecurityScheme is specified by OpenAPI/Swagger standard version 3. @@ -395,12 +396,7 @@ func (flow *OAuthFlow) validate(ctx context.Context, typ oAuthFlowType, opts ... ctx = WithValidationOptions(ctx, opts...) typeIn := func(types ...oAuthFlowType) bool { - for _, ty := range types { - if ty == typ { - return true - } - } - return false + return slices.Contains(types, typ) } if in := typeIn(oAuthFlowTypeImplicit, oAuthFlowAuthorizationCode); true { diff --git a/openapi3/security_scheme_test.go b/openapi3/security_scheme_test.go index 790414ca2..115564e73 100644 --- a/openapi3/security_scheme_test.go +++ b/openapi3/security_scheme_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -20,7 +19,7 @@ func TestSecuritySchemaExample(t *testing.T) { err := ss.UnmarshalJSON(example.raw) require.NoError(t, err) - err = ss.Validate(context.Background()) + err = ss.Validate(t.Context()) if example.valid { require.NoError(t, err) } else { diff --git a/openapi3/server_test.go b/openapi3/server_test.go index c59b86e56..e1e92ce0b 100644 --- a/openapi3/server_test.go +++ b/openapi3/server_test.go @@ -1,7 +1,6 @@ package openapi3 import ( - "context" "errors" "testing" @@ -35,7 +34,7 @@ func TestServerParamValuesWithPath(t *testing.T) { "http://domain0.domain1.example.com/a/b-version/c/d": newServerMatch("/d", "domain0", "domain1", "b", "", ""), "http://domain0.domain1.example.com/a/1.0.0-version/c/d": newServerMatch("/d", "domain0", "domain1", "1.0.0", "", ""), } { - t.Run(input, testServerParamValues(t, server, input, expected)) + t.Run(input, testServerParamValues(server, input, expected)) } } @@ -46,7 +45,7 @@ func TestServerParamValuesNoPath(t *testing.T) { for input, expected := range map[string]*serverMatch{ "https://domain0.domain1.example.com/": newServerMatch("/", "domain0", "domain1"), } { - t.Run(input, testServerParamValues(t, server, input, expected)) + t.Run(input, testServerParamValues(server, input, expected)) } } @@ -80,7 +79,7 @@ func TestServerValidation(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := context.Background() + c := t.Context() validationErr := test.input.Validate(c) require.Equal(t, test.expectedError, validationErr, "expected errors (or lack of) to match") @@ -88,7 +87,7 @@ func TestServerValidation(t *testing.T) { } } -func testServerParamValues(t *testing.T, server *Server, input string, expected *serverMatch) func(*testing.T) { +func testServerParamValues(server *Server, input string, expected *serverMatch) func(*testing.T) { return func(t *testing.T) { args, remaining, ok := server.MatchRawURL(input) if expected == nil { @@ -192,7 +191,7 @@ func TestServersBasePath(t *testing.T) { }, } { t.Run(testcase.title, func(t *testing.T) { - err := testcase.servers.Validate(context.Background()) + err := testcase.servers.Validate(t.Context()) require.NoError(t, err) got, err := testcase.servers.BasePath() diff --git a/openapi3/v3_apis_guru_openapi_directory_test.go b/openapi3/v3_apis_guru_openapi_directory_test.go index 0d628328f..85fb6071f 100644 --- a/openapi3/v3_apis_guru_openapi_directory_test.go +++ b/openapi3/v3_apis_guru_openapi_directory_test.go @@ -12,8 +12,9 @@ import ( "strings" "testing" - "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" ) var goldens = filepath.Join("testdata", "apis_guru_openapi_directory") diff --git a/openapi3filter/csv_file_upload_test.go b/openapi3filter/csv_file_upload_test.go index 89efb96d9..4a7a573c7 100644 --- a/openapi3filter/csv_file_upload_test.go +++ b/openapi3filter/csv_file_upload_test.go @@ -2,7 +2,6 @@ package openapi3filter_test import ( "bytes" - "context" "io" "mime/multipart" "net/http" @@ -107,7 +106,7 @@ baz,qux,quux`, require.NoError(t, err) if err = openapi3filter.ValidateRequestBody( - context.Background(), + req.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3filter/errors.go b/openapi3filter/errors.go index ea7c7c312..1039bed51 100644 --- a/openapi3filter/errors.go +++ b/openapi3filter/errors.go @@ -33,9 +33,8 @@ func (err *RequestError) Error() string { return fmt.Sprintf("parameter %q in %s has an error: %s", v.Name, v.In, reason) } else if v := err.RequestBody; v != nil { return fmt.Sprintf("request body has an error: %s", reason) - } else { - return reason } + return reason } func (err RequestError) Unwrap() error { diff --git a/openapi3filter/issue201_test.go b/openapi3filter/issue201_test.go index ec0b2a1f1..7e25f1167 100644 --- a/openapi3filter/issue201_test.go +++ b/openapi3filter/issue201_test.go @@ -1,7 +1,6 @@ package openapi3filter import ( - "context" "io" "net/http" "strings" @@ -122,7 +121,7 @@ paths: route, pathParams, err := router.FindRoute(r) require.NoError(t, err) - err = ValidateResponse(context.Background(), &ResponseValidationInput{ + err = ValidateResponse(t.Context(), &ResponseValidationInput{ RequestValidationInput: &RequestValidationInput{ Request: r, PathParams: pathParams, diff --git a/openapi3filter/issue436_test.go b/openapi3filter/issue436_test.go index fa106c5a1..0986d86f7 100644 --- a/openapi3filter/issue436_test.go +++ b/openapi3filter/issue436_test.go @@ -2,7 +2,6 @@ package openapi3filter_test import ( "bytes" - "context" "io" "mime/multipart" "net/http" @@ -121,7 +120,7 @@ components: } if err = openapi3filter.ValidateRequestBody( - context.Background(), + req.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3filter/issue722_test.go b/openapi3filter/issue722_test.go index 73648e0fe..9c250c109 100644 --- a/openapi3filter/issue722_test.go +++ b/openapi3filter/issue722_test.go @@ -2,7 +2,6 @@ package openapi3filter_test import ( "bytes" - "context" "io" "mime/multipart" "net/http" @@ -120,7 +119,7 @@ components: } if err = openapi3filter.ValidateRequestBody( - context.Background(), + t.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3filter/issue733_test.go b/openapi3filter/issue733_test.go index f43a826e8..933402dfb 100644 --- a/openapi3filter/issue733_test.go +++ b/openapi3filter/issue733_test.go @@ -2,7 +2,6 @@ package openapi3filter_test import ( "bytes" - "context" "encoding/json" "math" "math/big" @@ -65,7 +64,7 @@ paths: require.NoError(t, err) err = openapi3filter.ValidateRequest( - context.Background(), + t.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3filter/issue743_test.go b/openapi3filter/issue743_test.go index 24122e104..fe437be67 100644 --- a/openapi3filter/issue743_test.go +++ b/openapi3filter/issue743_test.go @@ -9,11 +9,12 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/getkin/kin-openapi/openapi3" "github.com/getkin/kin-openapi/openapi3filter" "github.com/getkin/kin-openapi/routers/gorillamux" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestValidateRequestWithAnAuthenticatorFunc_CanConsumeTheRequestBody(t *testing.T) { @@ -63,7 +64,7 @@ security: require.NoError(t, err) err = openapi3filter.ValidateRequest( - context.Background(), + t.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3filter/issue949_test.go b/openapi3filter/issue949_test.go index f87fae378..6845dc8b5 100644 --- a/openapi3filter/issue949_test.go +++ b/openapi3filter/issue949_test.go @@ -12,10 +12,11 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/getkin/kin-openapi/openapi3" "github.com/getkin/kin-openapi/openapi3filter" "github.com/getkin/kin-openapi/routers/gorillamux" - "github.com/stretchr/testify/require" ) const testSchema = ` @@ -60,7 +61,7 @@ func TestIssue949(t *testing.T) { doc, err := loader.LoadFromData([]byte(testSchema)) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.NoError(t, err) router, err := gorillamux.NewRouter(doc) diff --git a/openapi3filter/issue991_test.go b/openapi3filter/issue991_test.go index 10737ea93..317ea133e 100644 --- a/openapi3filter/issue991_test.go +++ b/openapi3filter/issue991_test.go @@ -1,7 +1,6 @@ package openapi3filter import ( - "context" "net/http" "testing" @@ -128,7 +127,7 @@ func TestValidateRequestDefault(t *testing.T) { PathParams: pathParams, Route: route, } - err = ValidateRequest(context.Background(), validationInput) + err = ValidateRequest(t.Context(), validationInput) assert.IsType(t, tc.expectedErr, err, "ValidateRequest(): error = %v, expectedError %v", err, tc.expectedErr) if tc.expectedErr != nil { return diff --git a/openapi3filter/middleware_test.go b/openapi3filter/middleware_test.go index d492bec0c..197481a10 100644 --- a/openapi3filter/middleware_test.go +++ b/openapi3filter/middleware_test.go @@ -144,21 +144,21 @@ func (h *validatorTestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) w.Header().Set("Content-Type", h.contentType) if h.errStatusCode != 0 { w.WriteHeader(h.errStatusCode) - w.Write([]byte(h.errBody)) + _, _ = w.Write([]byte(h.errBody)) return } if !testUrlRE.MatchString(r.URL.Path) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(h.errBody)) + _, _ = w.Write([]byte(h.errBody)) return } switch r.Method { case "GET": w.WriteHeader(http.StatusOK) - w.Write([]byte(h.getBody)) + _, _ = w.Write([]byte(h.getBody)) case "POST": w.WriteHeader(http.StatusCreated) - w.Write([]byte(h.postBody)) + _, _ = w.Write([]byte(h.postBody)) default: http.Error(w, h.errBody, http.StatusMethodNotAllowed) } @@ -494,7 +494,7 @@ paths: // Customize validation error responses to use JSON w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) - json.NewEncoder(w).Encode(map[string]any{ + _ = json.NewEncoder(w).Encode(map[string]any{ "status": status, "message": http.StatusText(status), }) diff --git a/openapi3filter/options_test.go b/openapi3filter/options_test.go index fd19329ff..f0e320c62 100644 --- a/openapi3filter/options_test.go +++ b/openapi3filter/options_test.go @@ -1,7 +1,6 @@ package openapi3filter_test import ( - "context" "fmt" "net/http" "strings" @@ -74,7 +73,7 @@ paths: Route: route, Options: opts, } - err = openapi3filter.ValidateRequest(context.Background(), validationInput) + err = openapi3filter.ValidateRequest(req.Context(), validationInput) fmt.Println(err.Error()) diff --git a/openapi3filter/req_resp_decoder.go b/openapi3filter/req_resp_decoder.go index 0321390e7..2c9517ca7 100644 --- a/openapi3filter/req_resp_decoder.go +++ b/openapi3filter/req_resp_decoder.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "maps" "mime" "mime/multipart" "net/http" @@ -540,14 +541,14 @@ func (d *urlValuesDecoder) DecodeArray(param string, sm *openapi3.SerializationM } values = strings.Split(values[0], delim) } - val, err := d.parseArray(values, sm, schema) + val, err := d.parseArray(values, schema) return val, ok, err } // parseArray returns an array that contains items from a raw array. // Every item is parsed as a primitive value. // The function returns an error when an error happened while parse array's items. -func (d *urlValuesDecoder) parseArray(raw []string, sm *openapi3.SerializationMethod, schemaRef *openapi3.SchemaRef) ([]any, error) { +func (d *urlValuesDecoder) parseArray(raw []string, schemaRef *openapi3.SchemaRef) ([]any, error) { var value []any for i, v := range raw { @@ -1058,9 +1059,7 @@ func buildFromSchemas(schemas openapi3.SchemaRefs, params map[string]any, mapKey if err == nil && val != nil { if m, ok := val.(map[string]any); ok { - for k, v := range m { - resultMap[k] = v - } + maps.Copy(resultMap, m) continue } @@ -1512,7 +1511,7 @@ func MultipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.S return nil, fmt.Errorf("part %s: %w", name, err) } - // Parse primitive types when no content type is explicitely provided, or the content type is set to text/plain + // Parse primitive types when no content type is explicitly provided, or the content type is set to text/plain if contentType := partHeader.Get(headerCT); contentType == "" || contentType == "text/plain" { if value, err = parsePrimitive(value.(string), valueSchema); err != nil { if v, ok := err.(*ParseError); ok { @@ -1528,23 +1527,15 @@ func MultipartBodyDecoder(body io.Reader, header http.Header, schema *openapi3.S allTheProperties := make(map[string]*openapi3.SchemaRef) if len(schema.Value.AllOf) > 0 { for _, sr := range schema.Value.AllOf { - for k, v := range sr.Value.Properties { - allTheProperties[k] = v - } + maps.Copy(allTheProperties, sr.Value.Properties) if addProps := sr.Value.AdditionalProperties.Schema; addProps != nil { - for k, v := range addProps.Value.Properties { - allTheProperties[k] = v - } + maps.Copy(allTheProperties, addProps.Value.Properties) } } } else { - for k, v := range schema.Value.Properties { - allTheProperties[k] = v - } + maps.Copy(allTheProperties, schema.Value.Properties) if addProps := schema.Value.AdditionalProperties.Schema; addProps != nil { - for k, v := range addProps.Value.Properties { - allTheProperties[k] = v - } + maps.Copy(allTheProperties, addProps.Value.Properties) } } diff --git a/openapi3filter/req_resp_decoder_test.go b/openapi3filter/req_resp_decoder_test.go index e264d2d92..cbeb49d9d 100644 --- a/openapi3filter/req_resp_decoder_test.go +++ b/openapi3filter/req_resp_decoder_test.go @@ -2,7 +2,6 @@ package openapi3filter import ( "bytes" - "context" "encoding/json" "fmt" "io" @@ -22,8 +21,8 @@ import ( ) var ( - explode = openapi3.Ptr(true) - noExplode = openapi3.Ptr(false) + explode = new(true) + noExplode = new(false) arrayOf = func(items *openapi3.SchemaRef) *openapi3.SchemaRef { return &openapi3.SchemaRef{Value: &openapi3.Schema{Type: &openapi3.Types{"array"}, Items: items}} } @@ -82,14 +81,6 @@ var ( }, }, } - anyofSchemaObject = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - AnyOf: []*openapi3.SchemaRef{ - objectOneRSchema, - objectTwoRSchema, - }, - }, - } stringArraySchema = arrayOf(stringSchema) integerArraySchema = arrayOf(integerSchema) objectSchema = objectOf("id", stringSchema, "name", stringSchema) @@ -1594,7 +1585,7 @@ func TestDecodeParameter(t *testing.T) { Responses: openapi3.NewResponses(openapi3.WithStatus(200, &openapi3.ResponseRef{Value: openapi3.NewResponse().WithDescription("OK")})), } doc.AddOperation(path, http.MethodGet, op) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.NoError(t, err) router, err := legacyrouter.NewRouter(doc) require.NoError(t, err) @@ -1683,16 +1674,19 @@ func TestDecodeBody(t *testing.T) { {name: "f", contentType: "application/json", data: strings.NewReader(`{"foo1": "foo1"}`), filename: "f1"}, {name: "f", contentType: "application/pdf", data: strings.NewReader("foo2"), filename: "f2"}, }) + require.NoError(t, err) multipartBinaryEncodingCTUnsupported, multipartMimeBinaryEncodingCTUnsupported, err := newTestMultipartForm([]*testFormPart{ {name: "b", contentType: "application/json", data: strings.NewReader(`{"bar1": "bar1"}`), filename: "b1"}, {name: "d", contentType: "application/pdf", data: strings.NewReader("doo1"), filename: "d1"}, }) + require.NoError(t, err) multipartBinaryEncodingCTNotMatching, multipartMimeBinaryEncodingCTNotMatching, err := newTestMultipartForm([]*testFormPart{ {name: "b", contentType: "application/json", data: strings.NewReader(`{"bar1": "bar1"}`), filename: "b1"}, {name: "d", contentType: "application/pdf", data: strings.NewReader("doo1"), filename: "d1"}, }) + require.NoError(t, err) testCases := []struct { name string @@ -1757,7 +1751,7 @@ func TestDecodeBody(t *testing.T) { WithProperty("b", openapi3.NewIntegerSchema()). WithProperty("c", openapi3.NewArraySchema().WithItems(openapi3.NewStringSchema())), encoding: map[string]*openapi3.Encoding{ - "c": {Style: openapi3.SerializationSpaceDelimited, Explode: openapi3.Ptr(false)}, + "c": {Style: openapi3.SerializationSpaceDelimited, Explode: new(false)}, }, want: map[string]any{"a": "a1", "b": int64(10), "c": []any{"c1", "c2"}}, }, @@ -1770,7 +1764,7 @@ func TestDecodeBody(t *testing.T) { WithProperty("b", openapi3.NewIntegerSchema()). WithProperty("c", openapi3.NewArraySchema().WithItems(openapi3.NewStringSchema())), encoding: map[string]*openapi3.Encoding{ - "c": {Style: openapi3.SerializationPipeDelimited, Explode: openapi3.Ptr(false)}, + "c": {Style: openapi3.SerializationPipeDelimited, Explode: new(false)}, }, want: map[string]any{"a": "a1", "b": int64(10), "c": []any{"c1", "c2"}}, }, @@ -1955,8 +1949,7 @@ func newTestMultipartForm(parts []*testFormPart) (io.Reader, string, error) { } func TestRegisterAndUnregisterBodyDecoder(t *testing.T) { - var decoder BodyDecoder - decoder = func(body io.Reader, h http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (decoded any, err error) { + var decoder BodyDecoder = func(body io.Reader, h http.Header, schema *openapi3.SchemaRef, encFn EncodingFn) (decoded any, err error) { var data []byte if data, err = io.ReadAll(body); err != nil { return diff --git a/openapi3filter/req_resp_encoder_test.go b/openapi3filter/req_resp_encoder_test.go index 7942dab93..86ff65918 100644 --- a/openapi3filter/req_resp_encoder_test.go +++ b/openapi3filter/req_resp_encoder_test.go @@ -9,8 +9,7 @@ import ( ) func TestRegisterAndUnregisterBodyEncoder(t *testing.T) { - var encoder BodyEncoder - encoder = func(body any) (data []byte, err error) { + var encoder BodyEncoder = func(body any) (data []byte, err error) { return []byte(strings.Join(body.([]string), ",")), nil } const contentType = "text/csv" diff --git a/openapi3filter/testdata/issue1100_test.go b/openapi3filter/testdata/issue1100_test.go index b5147dfe8..fdd490a3f 100644 --- a/openapi3filter/testdata/issue1100_test.go +++ b/openapi3filter/testdata/issue1100_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" - "github.com/getkin/kin-openapi/openapi3filter" "github.com/stretchr/testify/require" "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/openapi3filter" "github.com/getkin/kin-openapi/routers/gorillamux" ) diff --git a/openapi3filter/upload_arbitrary_file_test.go b/openapi3filter/upload_arbitrary_file_test.go index f0d771f04..fa7d185f5 100644 --- a/openapi3filter/upload_arbitrary_file_test.go +++ b/openapi3filter/upload_arbitrary_file_test.go @@ -2,7 +2,6 @@ package openapi3filter_test import ( "bytes" - "context" "io" "mime/multipart" "net/http" @@ -80,8 +79,8 @@ paths: fw, err := writer.CreatePart(h) require.NoError(t, err) - _, err = io.Copy(fw, bytes.NewReader(tt.zipData)) + _, err = io.Copy(fw, bytes.NewReader(tt.zipData)) require.NoError(t, err) } @@ -96,7 +95,7 @@ paths: require.NoError(t, err) if err = openapi3filter.ValidateRequestBody( - context.Background(), + t.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3filter/validate_request_example_test.go b/openapi3filter/validate_request_example_test.go index 653db3039..906bddeb4 100644 --- a/openapi3filter/validate_request_example_test.go +++ b/openapi3filter/validate_request_example_test.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "net/http" + "slices" "github.com/getkin/kin-openapi/openapi3" "github.com/getkin/kin-openapi/routers/gorillamux" @@ -56,14 +57,9 @@ paths: } for _, requiredScope := range ai.Scopes { - var allowed bool - for _, scope := range userScopes[user] { - if scope == requiredScope { - allowed = true - break - } - } - if !allowed { + if slices.Contains(userScopes[user], requiredScope) { + break + } else { return errForbidden } } diff --git a/openapi3filter/validate_request_test.go b/openapi3filter/validate_request_test.go index 3d0c9956b..0f257fe3a 100644 --- a/openapi3filter/validate_request_test.go +++ b/openapi3filter/validate_request_test.go @@ -201,7 +201,7 @@ components: AuthenticationFunc: verifyAPIKeyPresence, }, } - err = ValidateRequest(context.Background(), validationInput) + err = ValidateRequest(t.Context(), validationInput) assert.IsType(t, tc.expectedErr, err, "ValidateRequest(): error = %v, expectedError %v", err, tc.expectedErr) if tc.expectedErr != nil { return @@ -446,17 +446,18 @@ func TestValidateQueryParams(t *testing.T) { Responses: openapi3.NewResponses(openapi3.WithStatus(200, &openapi3.ResponseRef{Value: openapi3.NewResponse().WithDescription("OK")})), } doc.AddOperation("/test", http.MethodGet, op) - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) router, err := legacyrouter.NewRouter(doc) require.NoError(t, err) req, err := http.NewRequest(http.MethodGet, "http://test.org/test?"+tc.query, nil) + require.NoError(t, err) route, pathParams, err := router.FindRoute(req) require.NoError(t, err) input := &RequestValidationInput{Request: req, PathParams: pathParams, Route: route} - err = ValidateParameter(context.Background(), input, tc.param) + err = ValidateParameter(t.Context(), input, tc.param) if tc.err != nil { require.Error(t, err) @@ -475,10 +476,10 @@ func TestValidateQueryParams(t *testing.T) { return } - require.NoError(t, err) got, _, err := decodeStyledParameter(tc.param, input) + require.NoError(t, err) require.EqualValues(t, tc.want, got) }) } @@ -547,7 +548,7 @@ paths: route, pathParams, err := router.FindRoute(req) require.NoError(t, err) - err = ValidateRequest(context.Background(), &RequestValidationInput{ + err = ValidateRequest(t.Context(), &RequestValidationInput{ Request: req, PathParams: pathParams, Route: route, @@ -557,7 +558,7 @@ paths: }) require.NoError(t, err) - err = ValidateRequest(context.Background(), &RequestValidationInput{ + err = ValidateRequest(t.Context(), &RequestValidationInput{ Request: req, PathParams: pathParams, Route: route, diff --git a/openapi3filter/validate_response.go b/openapi3filter/validate_response.go index 2e0128b91..d055c7173 100644 --- a/openapi3filter/validate_response.go +++ b/openapi3filter/validate_response.go @@ -20,9 +20,7 @@ import ( // Note: One can tune the behavior of uniqueItems: true verification // by registering a custom function with openapi3.RegisterArrayUniqueItemsChecker func ValidateResponse(ctx context.Context, input *ResponseValidationInput) error { - req := input.RequestValidationInput.Request - switch req.Method { - case "HEAD": + if req := input.RequestValidationInput.Request; req.Method == http.MethodHead { return nil } status := input.Status diff --git a/openapi3filter/validation_error_test.go b/openapi3filter/validation_error_test.go index 8a1ff8262..fdc40e513 100644 --- a/openapi3filter/validation_error_test.go +++ b/openapi3filter/validation_error_test.go @@ -756,7 +756,8 @@ func runTest_Middleware(t *testing.T, handler http.Handler, encoder ErrorEncoder func TestValidationHandler_ServeHTTP(t *testing.T) { t.Run("errors on invalid requests", func(t *testing.T) { - httpCtx := context.WithValue(context.Background(), "pig", "tails") + type pig struct{} + httpCtx := context.WithValue(t.Context(), pig{}, "tails") r, err := http.NewRequest(http.MethodGet, "http://unknown-host.com/v2/pet", nil) require.NoError(t, err) r = r.WithContext(httpCtx) @@ -798,7 +799,8 @@ func TestValidationHandler_ServeHTTP(t *testing.T) { func TestValidationHandler_Middleware(t *testing.T) { t.Run("errors on invalid requests", func(t *testing.T) { - httpCtx := context.WithValue(context.Background(), "pig", "tails") + type pig struct{} + httpCtx := context.WithValue(t.Context(), pig{}, "tails") r, err := http.NewRequest(http.MethodGet, "http://unknown-host.com/v2/pet", nil) require.NoError(t, err) r = r.WithContext(httpCtx) diff --git a/openapi3filter/validation_kit.go b/openapi3filter/validation_kit.go index 9e11e4fc8..16951e476 100644 --- a/openapi3filter/validation_kit.go +++ b/openapi3filter/validation_kit.go @@ -81,5 +81,5 @@ func DefaultErrorEncoder(_ context.Context, err error, w http.ResponseWriter) { code = sc.StatusCode() } w.WriteHeader(code) - w.Write(body) + _, _ = w.Write(body) } diff --git a/openapi3filter/validation_test.go b/openapi3filter/validation_test.go index c6cec7195..1ac7ec4c2 100644 --- a/openapi3filter/validation_test.go +++ b/openapi3filter/validation_test.go @@ -156,10 +156,11 @@ func TestFilter(t *testing.T) { ), } - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) router, err := legacyrouter.NewRouter(doc) require.NoError(t, err) + expectWithDecoder := func(req ExampleRequest, resp ExampleResponse, decoder ContentParameterDecoder) error { t.Logf("Request: %s %s", req.Method, req.URL) httpReq, err := http.NewRequest(req.Method, req.URL, marshalReader(req.Body)) @@ -177,7 +178,7 @@ func TestFilter(t *testing.T) { Route: route, ParamDecoder: decoder, } - if err := ValidateRequest(context.Background(), requestValidationInput); err != nil { + if err := ValidateRequest(t.Context(), requestValidationInput); err != nil { return err } t.Logf("Response: %d", resp.Status) @@ -195,10 +196,11 @@ func TestFilter(t *testing.T) { require.NoError(t, err) responseValidationInput.SetBodyBytes(data) } - err = ValidateResponse(context.Background(), responseValidationInput) + err = ValidateResponse(t.Context(), responseValidationInput) require.NoError(t, err) return nil } + expect := func(req ExampleRequest, resp ExampleResponse) error { return expectWithDecoder(req, resp, nil) } @@ -431,7 +433,7 @@ func TestValidateRequestBody(t *testing.T) { req.Header.Set(headerCT, tc.mime) } inp := &RequestValidationInput{Request: req} - err := ValidateRequestBody(context.Background(), inp, tc.body) + err := ValidateRequestBody(t.Context(), inp, tc.body) if tc.wantErr == nil { require.NoError(t, err) @@ -563,7 +565,7 @@ func TestRootSecurityRequirementsAreUsedIfNotProvidedAtTheOperationLevel(t *test }) } - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) router, err := legacyrouter.NewRouter(doc) require.NoError(t, err) @@ -604,7 +606,7 @@ func TestRootSecurityRequirementsAreUsedIfNotProvidedAtTheOperationLevel(t *test } // Validate the request - err = ValidateRequest(context.Background(), &req) + err = ValidateRequest(t.Context(), &req) require.NoError(t, err) for securityRequirement, validated := range schemesValidated { @@ -688,7 +690,7 @@ func TestAnySecurityRequirementMet(t *testing.T) { }) } - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) router, err := legacyrouter.NewRouter(&doc) require.NoError(t, err) @@ -711,7 +713,7 @@ func TestAnySecurityRequirementMet(t *testing.T) { } // Validate the security requirements - err = ValidateSecurityRequirements(context.Background(), &req, *route.Operation.Security) + err = ValidateSecurityRequirements(t.Context(), &req, *route.Operation.Security) // If there should have been an error if tc.error { @@ -790,7 +792,7 @@ func TestAllSchemesMet(t *testing.T) { }) } - err := doc.Validate(context.Background()) + err := doc.Validate(t.Context()) require.NoError(t, err) router, err := legacyrouter.NewRouter(&doc) require.NoError(t, err) @@ -813,7 +815,7 @@ func TestAllSchemesMet(t *testing.T) { } // Validate the security requirements - err = ValidateSecurityRequirements(context.Background(), &req, *route.Operation.Security) + err = ValidateSecurityRequirements(t.Context(), &req, *route.Operation.Security) // If there should have been an error if tc.error { diff --git a/openapi3filter/zip_file_upload_test.go b/openapi3filter/zip_file_upload_test.go index a61804062..4e82ad483 100644 --- a/openapi3filter/zip_file_upload_test.go +++ b/openapi3filter/zip_file_upload_test.go @@ -2,7 +2,6 @@ package openapi3filter_test import ( "bytes" - "context" "io" "mime/multipart" "net/http" @@ -104,7 +103,7 @@ paths: require.NoError(t, err) if err = openapi3filter.ValidateRequestBody( - context.Background(), + t.Context(), &openapi3filter.RequestValidationInput{ Request: req, PathParams: pathParams, diff --git a/openapi3gen/field_info.go b/openapi3gen/field_info.go index 8017cf1c5..70a148c8c 100644 --- a/openapi3gen/field_info.go +++ b/openapi3gen/field_info.go @@ -30,7 +30,7 @@ func appendFields(fields []theFieldInfo, parentIndex []int, t reflect.Type) []th // For each field numField := t.NumField() iteration: - for i := 0; i < numField; i++ { + for i := range numField { f := t.Field(i) index := make([]int, 0, len(parentIndex)+1) index = append(index, parentIndex...) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 5d9b64abf..8af688823 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -7,6 +7,7 @@ import ( "math" "reflect" "regexp" + "slices" "strings" "time" @@ -178,7 +179,7 @@ func (g *Generator) generateSchemaRefFor(parents []*theTypeInfo, t reflect.Type, func getStructField(t reflect.Type, fieldInfo theFieldInfo) reflect.StructField { var ff reflect.StructField // fieldInfo.Index is an array of indexes starting from the root of the type - for i := 0; i < len(fieldInfo.Index); i++ { + for i := range len(fieldInfo.Index) { ff = t.Field(fieldInfo.Index[i]) t = ff.Type for t.Kind() == reflect.Ptr { @@ -190,10 +191,8 @@ func getStructField(t reflect.Type, fieldInfo theFieldInfo) reflect.StructField func (g *Generator) generateWithoutSaving(parents []*theTypeInfo, t reflect.Type, name string, tag reflect.StructTag) (*openapi3.SchemaRef, error) { typeInfo := getTypeInfo(t) - for _, parent := range parents { - if parent == typeInfo { - return nil, &CycleError{} - } + if slices.Contains(parents, typeInfo) { + return nil, &CycleError{} } isRoot := cap(parents) == 0 if isRoot { @@ -335,7 +334,7 @@ func (g *Generator) generateWithoutSaving(parents []*theTypeInfo, t reflect.Type if _, ok := g.componentSchemaRefs[typeName]; ok && g.opts.exportComponentSchemas.ExportComponentSchemas { // Check if we have already parsed this component schema ref based on the name of the struct // and use that if so - return openapi3.NewSchemaRef(fmt.Sprintf("#/components/schemas/%s", typeName), schema), nil + return openapi3.NewSchemaRef("#/components/schemas/"+typeName, schema), nil } for _, fieldInfo := range typeInfo.Fields { @@ -473,7 +472,7 @@ func (g *Generator) generateCycleSchemaRef(t reflect.Type, schema *openapi3.Sche } g.componentSchemaRefs[typeName] = struct{}{} - return openapi3.NewSchemaRef(fmt.Sprintf("#/components/schemas/%s", typeName), schema) + return openapi3.NewSchemaRef("#/components/schemas/"+typeName, schema) } var RefSchemaRef = openapi3.NewSchemaRef("Ref", diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index dbed33867..b19803fa7 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -214,7 +214,7 @@ func TestExportedNonTagged(t *testing.T) { type Bla struct { A string Another string `json:"another"` - yetAnother string // unused because unexported + yetAnother string //nolint:unused // unused because unexported EvenAYaml string `yaml:"even_a_yaml"` } diff --git a/routers/gorillamux/router.go b/routers/gorillamux/router.go index 106e236b9..bf502e6ff 100644 --- a/routers/gorillamux/router.go +++ b/routers/gorillamux/router.go @@ -104,7 +104,7 @@ func (r *Router) FindRoute(req *http.Request) (*routers.Route, map[string]string for i, m := range r.muxes { var match mux.RouteMatch if m.muxRoute.Match(req, &match) { - if err := match.MatchErr; err != nil { + if err := match.MatchErr; err != nil { //nolint:staticcheck // What then? } vars := match.Vars diff --git a/routers/gorillamux/router_test.go b/routers/gorillamux/router_test.go index cd87d8ab5..abe733276 100644 --- a/routers/gorillamux/router_test.go +++ b/routers/gorillamux/router_test.go @@ -298,6 +298,7 @@ func TestServerOverrideAtPathLevel(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "https://another.com/hello", nil) require.NoError(t, err) route, _, err := router.FindRoute(req) + require.NoError(t, err) require.Equal(t, "/hello", route.Path) req, err = http.NewRequest(http.MethodGet, "https://example.com/hello", nil) diff --git a/routers/issue356_test.go b/routers/issue356_test.go index 100e0183d..1c3528393 100644 --- a/routers/issue356_test.go +++ b/routers/issue356_test.go @@ -1,7 +1,6 @@ package routers_test import ( - "context" "io" "net/http" "net/http/httptest" @@ -62,11 +61,11 @@ paths: ``: true, } { - loader := &openapi3.Loader{Context: context.Background()} + loader := &openapi3.Loader{Context: t.Context()} t.Logf("using servers: %q (%v)", servers, expectError) doc, err := loader.LoadFromData(spec(servers)) require.NoError(t, err) - err = doc.Validate(context.Background()) + err = doc.Validate(t.Context()) require.NoError(t, err) gorillamuxNewRouterWrapped := func(doc *openapi3.T, opts ...openapi3.ValidationOption) (routers.Router, error) { return gorillamux.NewRouter(doc) @@ -95,7 +94,7 @@ paths: PathParams: pathParams, Route: route, } - err = openapi3filter.ValidateRequest(context.Background(), requestValidationInput) + err = openapi3filter.ValidateRequest(t.Context(), requestValidationInput) require.NoError(t, err) } @@ -105,7 +104,8 @@ paths: route, pathParams, err := router.FindRoute(r) if err != nil { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + _, err := w.Write([]byte(err.Error())) + require.NoError(t, err) return } @@ -118,7 +118,8 @@ paths: require.NoError(t, err) w.Header().Set("Content-Type", "application/json") - w.Write([]byte("{}")) + _, err = w.Write([]byte("{}")) + require.NoError(t, err) })) defer ts.Close() diff --git a/routers/legacy/router_test.go b/routers/legacy/router_test.go index a3183b78b..ed65bba84 100644 --- a/routers/legacy/router_test.go +++ b/routers/legacy/router_test.go @@ -211,6 +211,8 @@ func TestRouter(t *testing.T) { require.Error(t, err) r, err = NewRouter(doc) require.Error(t, err) + require.Nil(t, r) r, err = NewRouter(doc, openapi3.DisableExamplesValidation()) require.NoError(t, err) + require.NotNil(t, r) }