Skip to content

Commit

Permalink
introduce AllowExtraSiblingFields
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Fenoll <[email protected]>
  • Loading branch information
fenollp committed Jan 1, 2023
1 parent c988603 commit e819a65
Show file tree
Hide file tree
Showing 25 changed files with 231 additions and 45 deletions.
2 changes: 1 addition & 1 deletion openapi3/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp
}
}

return validateExtensions(components.Extensions)
return validateExtensions(ctx, components.Extensions)
}

const identifierPattern = `^[a-zA-Z0-9._-]+$`
Expand Down
4 changes: 2 additions & 2 deletions openapi3/discriminator.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (discriminator *Discriminator) UnmarshalJSON(data []byte) error {

// Validate returns an error if Discriminator does not comply with the OpenAPI spec.
func (discriminator *Discriminator) Validate(ctx context.Context, opts ...ValidationOption) error {
// ctx = WithValidationOptions(ctx, opts...)
ctx = WithValidationOptions(ctx, opts...)

return validateExtensions(discriminator.Extensions)
return validateExtensions(ctx, discriminator.Extensions)
}
2 changes: 1 addition & 1 deletion openapi3/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,5 @@ func (encoding *Encoding) Validate(ctx context.Context, opts ...ValidationOption
return fmt.Errorf("serialization method with style=%q and explode=%v is not supported by media type", sm.Style, sm.Explode)
}

return validateExtensions(encoding.Extensions)
return validateExtensions(ctx, encoding.Extensions)
}
4 changes: 2 additions & 2 deletions openapi3/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (example *Example) UnmarshalJSON(data []byte) error {

// Validate returns an error if Example does not comply with the OpenAPI spec.
func (example *Example) Validate(ctx context.Context, opts ...ValidationOption) error {
// ctx = WithValidationOptions(ctx, opts...)
ctx = WithValidationOptions(ctx, opts...)

if example.Value != nil && example.ExternalValue != "" {
return errors.New("value and externalValue are mutually exclusive")
Expand All @@ -89,5 +89,5 @@ func (example *Example) Validate(ctx context.Context, opts ...ValidationOption)
return errors.New("no value or externalValue field")
}

return validateExtensions(example.Extensions)
return validateExtensions(ctx, example.Extensions)
}
5 changes: 4 additions & 1 deletion openapi3/extension.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package openapi3

import (
"context"
"fmt"
"sort"
"strings"
)

func validateExtensions(extensions map[string]interface{}) error { // FIXME: newtype + Validate(...)
func validateExtensions(ctx context.Context, extensions map[string]interface{}) error { // FIXME: newtype + Validate(...)
var unknowns []string
for k := range extensions {
if !strings.HasPrefix(k, "x-") {
unknowns = append(unknowns, k)
}
}

if len(unknowns) != 0 {
sort.Strings(unknowns)
return fmt.Errorf("extra sibling fields: %+v", unknowns)
}

return nil
}
4 changes: 2 additions & 2 deletions openapi3/external_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (e *ExternalDocs) UnmarshalJSON(data []byte) error {

// Validate returns an error if ExternalDocs does not comply with the OpenAPI spec.
func (e *ExternalDocs) Validate(ctx context.Context, opts ...ValidationOption) error {
// ctx = WithValidationOptions(ctx, opts...)
ctx = WithValidationOptions(ctx, opts...)

if e.URL == "" {
return errors.New("url is required")
Expand All @@ -57,5 +57,5 @@ func (e *ExternalDocs) Validate(ctx context.Context, opts ...ValidationOption) e
return fmt.Errorf("url is incorrect: %w", err)
}

return validateExtensions(e.Extensions)
return validateExtensions(ctx, e.Extensions)
}
10 changes: 5 additions & 5 deletions openapi3/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (info *Info) Validate(ctx context.Context, opts ...ValidationOption) error
return errors.New("value of title must be a non-empty string")
}

return validateExtensions(info.Extensions)
return validateExtensions(ctx, info.Extensions)
}

// Contact is specified by OpenAPI/Swagger standard version 3.
Expand Down Expand Up @@ -132,9 +132,9 @@ func (contact *Contact) UnmarshalJSON(data []byte) error {

// Validate returns an error if Contact does not comply with the OpenAPI spec.
func (contact *Contact) Validate(ctx context.Context, opts ...ValidationOption) error {
// ctx = WithValidationOptions(ctx, opts...)
ctx = WithValidationOptions(ctx, opts...)

return validateExtensions(contact.Extensions)
return validateExtensions(ctx, contact.Extensions)
}

// License is specified by OpenAPI/Swagger standard version 3.
Expand Down Expand Up @@ -175,11 +175,11 @@ func (license *License) UnmarshalJSON(data []byte) error {

// Validate returns an error if License does not comply with the OpenAPI spec.
func (license *License) Validate(ctx context.Context, opts ...ValidationOption) error {
// ctx = WithValidationOptions(ctx, opts...)
ctx = WithValidationOptions(ctx, opts...)

if license.Name == "" {
return errors.New("value of license name must be a non-empty string")
}

return validateExtensions(license.Extensions)
return validateExtensions(ctx, license.Extensions)
}
40 changes: 40 additions & 0 deletions openapi3/issue513_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,43 @@ components:
err = doc.Validate(sl.Context)
require.ErrorContains(t, err, `extra sibling fields: [description]`)
}

func TestIssue513KOMixesRefAlongWithOtherFieldsAllowed(t *testing.T) {
spec := `
openapi: "3.0.3"
info:
title: 'My app'
version: 1.0.0
description: 'An API'
paths:
/v1/operation:
delete:
summary: Delete something
responses:
200:
description: A sibling field that the spec says is ignored
$ref: '#/components/responses/SomeResponseBody'
components:
responses:
SomeResponseBody:
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
type: object
description: An error response body.
properties:
message:
description: A detailed message describing the error.
type: string
`[1:]
sl := NewLoader()
doc, err := sl.LoadFromData([]byte(spec))
require.NoError(t, err)
err = doc.Validate(sl.Context, AllowExtraSiblingFields("description"))
require.NoError(t, err)
}
4 changes: 2 additions & 2 deletions openapi3/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (link *Link) UnmarshalJSON(data []byte) error {

// Validate returns an error if Link does not comply with the OpenAPI spec.
func (link *Link) Validate(ctx context.Context, opts ...ValidationOption) error {
// ctx = WithValidationOptions(ctx, opts...)
ctx = WithValidationOptions(ctx, opts...)

if link.OperationID == "" && link.OperationRef == "" {
return errors.New("missing operationId or operationRef on link")
Expand All @@ -97,5 +97,5 @@ func (link *Link) Validate(ctx context.Context, opts ...ValidationOption) error
return fmt.Errorf("operationId %q and operationRef %q are mutually exclusive", link.OperationID, link.OperationRef)
}

return validateExtensions(link.Extensions)
return validateExtensions(ctx, link.Extensions)
}
2 changes: 1 addition & 1 deletion openapi3/media_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (mediaType *MediaType) Validate(ctx context.Context, opts ...ValidationOpti
}
}

return validateExtensions(mediaType.Extensions)
return validateExtensions(ctx, mediaType.Extensions)
}

// JSONLookup implements github.com/go-openapi/jsonpointer#JSONPointable
Expand Down
2 changes: 1 addition & 1 deletion openapi3/openapi3.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,5 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
}
}

return validateExtensions(doc.Extensions)
return validateExtensions(ctx, doc.Extensions)
}
2 changes: 1 addition & 1 deletion openapi3/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,5 +212,5 @@ func (operation *Operation) Validate(ctx context.Context, opts ...ValidationOpti
}
}

return validateExtensions(operation.Extensions)
return validateExtensions(ctx, operation.Extensions)
}
2 changes: 1 addition & 1 deletion openapi3/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,5 +414,5 @@ func (parameter *Parameter) Validate(ctx context.Context, opts ...ValidationOpti
}
}

return validateExtensions(parameter.Extensions)
return validateExtensions(ctx, parameter.Extensions)
}
2 changes: 1 addition & 1 deletion openapi3/path_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,5 @@ func (pathItem *PathItem) Validate(ctx context.Context, opts ...ValidationOption
}
}

return validateExtensions(pathItem.Extensions)
return validateExtensions(ctx, pathItem.Extensions)
}
Loading

0 comments on commit e819a65

Please sign in to comment.