diff --git a/openapi3/extension.go b/openapi3/extension.go index c29959091..37f6b01e5 100644 --- a/openapi3/extension.go +++ b/openapi3/extension.go @@ -8,11 +8,19 @@ import ( ) func validateExtensions(ctx context.Context, extensions map[string]interface{}) error { // FIXME: newtype + Validate(...) + allowed := getValidationOptions(ctx).extraSiblingFieldsAllowed + var unknowns []string for k := range extensions { - if !strings.HasPrefix(k, "x-") { - unknowns = append(unknowns, k) + if strings.HasPrefix(k, "x-") { + continue + } + if allowed != nil { + if _, ok := allowed[k]; ok { + continue + } } + unknowns = append(unknowns, k) } if len(unknowns) != 0 { diff --git a/openapi3/issue513_test.go b/openapi3/issue513_test.go index 332b9226e..442eac848 100644 --- a/openapi3/issue513_test.go +++ b/openapi3/issue513_test.go @@ -7,6 +7,71 @@ import ( "github.com/stretchr/testify/require" ) +func TestExtraSiblingsInRemoteRef(t *testing.T) { + spec := []byte(` +openapi: 3.0.1 +servers: +- url: http://localhost:5000 +info: + version: v1 + title: Products api + contact: + name: me + email: me@github.com + description: This is a sample +paths: + /categories: + get: + summary: Provides the available categories for the store + operationId: list-categories + responses: + '200': + description: this is a desc + content: + application/json: + schema: + $ref: http://schemas.sentex.io/store/categories.json +`[1:]) + + // When that site fails to respond: + // see https://github.com/getkin/kin-openapi/issues/495 + + // http://schemas.sentex.io/store/categories.json + // { + // "$id": "http://schemas.sentex.io/store/categories.json", + // "$schema": "http://json-schema.org/draft-07/schema#", + // "description": "array of category strings", + // "type": "array", + // "items": { + // "allOf": [ + // { + // "$ref": "http://schemas.sentex.io/store/category.json" + // } + // ] + // } + // } + + // http://schemas.sentex.io/store/category.json + // { + // "$id": "http://schemas.sentex.io/store/category.json", + // "$schema": "http://json-schema.org/draft-07/schema#", + // "description": "category name for products", + // "type": "string", + // "pattern": "^[A-Za-z0-9\\-]+$", + // "minimum": 1, + // "maximum": 30 + // } + + sl := NewLoader() + sl.IsExternalRefsAllowed = true + + doc, err := sl.LoadFromData(spec) + require.NoError(t, err) + + err = doc.Validate(sl.Context, AllowExtraSiblingFields("$id", "$schema")) + require.NoError(t, err) +} + func TestIssue513OKWithExtension(t *testing.T) { spec := ` openapi: "3.0.3" @@ -92,7 +157,7 @@ components: require.ErrorContains(t, err, `extra sibling fields: [schema]`) } -func TestIssue513KOMixesRefAlongWithOtherFields(t *testing.T) { +func TestIssue513KOMixesRefAlongWithOtherFieldsDisallowed(t *testing.T) { spec := ` openapi: "3.0.3" info: