From e429cc081c3c9b2ab3268593010cfbc11bdc1b53 Mon Sep 17 00:00:00 2001 From: Dmitriy Lukiyanchuk Date: Mon, 8 Aug 2022 19:27:31 +0300 Subject: [PATCH 1/4] Protect from recursion in openapi3.InternaliseRefs Fixes stack overflow panic when schema includes link to itself, like: ``` components: schemas: Item: type: object properties: Name: type: string ParentLink: $ref: '#/components/schemas/Item' ``` --- openapi3/internalize_refs.go | 66 ++++++++------- .../testdata/recursiveRef/components/Cat.yml | 4 + openapi3/testdata/recursiveRef/openapi.yml | 2 + .../recursiveRef/openapi.yml.internalized.yml | 8 ++ openapi3/visited.go | 81 +++++++++++++++++++ 5 files changed, 131 insertions(+), 30 deletions(-) create mode 100644 openapi3/testdata/recursiveRef/components/Cat.yml create mode 100644 openapi3/visited.go diff --git a/openapi3/internalize_refs.go b/openapi3/internalize_refs.go index 3e19b79a2..22aab397e 100644 --- a/openapi3/internalize_refs.go +++ b/openapi3/internalize_refs.go @@ -199,8 +199,8 @@ func (doc *T) addCallbackToSpec(c *CallbackRef, refNameResolver RefNameResolver) c.Ref = "#/components/callbacks/" + name } -func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver) { - if s == nil { +func (doc *T) derefSchema(ctx context.Context, s *Schema, refNameResolver RefNameResolver) { + if s == nil || isVisitedSchema(ctx, s) { return } @@ -208,28 +208,32 @@ func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver) { for _, s2 := range list { doc.addSchemaToSpec(s2, refNameResolver) if s2 != nil { - doc.derefSchema(s2.Value, refNameResolver) + doc.derefSchema(ctx, s2.Value, refNameResolver) } } } for _, s2 := range s.Properties { doc.addSchemaToSpec(s2, refNameResolver) + if s2 != nil { - doc.derefSchema(s2.Value, refNameResolver) + doc.derefSchema(ctx, s2.Value, refNameResolver) } } for _, ref := range []*SchemaRef{s.Not, s.AdditionalProperties, s.Items} { doc.addSchemaToSpec(ref, refNameResolver) if ref != nil { - doc.derefSchema(ref.Value, refNameResolver) + doc.derefSchema(ctx, ref.Value, refNameResolver) } } } -func (doc *T) derefHeaders(hs Headers, refNameResolver RefNameResolver) { +func (doc *T) derefHeaders(ctx context.Context, hs Headers, refNameResolver RefNameResolver) { for _, h := range hs { doc.addHeaderToSpec(h, refNameResolver) - doc.derefParameter(h.Value.Parameter, refNameResolver) + if isVisitedHeader(ctx, h.Value) { + continue + } + doc.derefParameter(ctx, h.Value.Parameter, refNameResolver) } } @@ -239,15 +243,15 @@ func (doc *T) derefExamples(es Examples, refNameResolver RefNameResolver) { } } -func (doc *T) derefContent(c Content, refNameResolver RefNameResolver) { +func (doc *T) derefContent(ctx context.Context, c Content, refNameResolver RefNameResolver) { for _, mediatype := range c { doc.addSchemaToSpec(mediatype.Schema, refNameResolver) if mediatype.Schema != nil { - doc.derefSchema(mediatype.Schema.Value, refNameResolver) + doc.derefSchema(ctx, mediatype.Schema.Value, refNameResolver) } doc.derefExamples(mediatype.Examples, refNameResolver) for _, e := range mediatype.Encoding { - doc.derefHeaders(e.Headers, refNameResolver) + doc.derefHeaders(ctx, e.Headers, refNameResolver) } } } @@ -258,30 +262,30 @@ func (doc *T) derefLinks(ls Links, refNameResolver RefNameResolver) { } } -func (doc *T) derefResponses(es Responses, refNameResolver RefNameResolver) { +func (doc *T) derefResponses(ctx context.Context, es Responses, refNameResolver RefNameResolver) { for _, e := range es { doc.addResponseToSpec(e, refNameResolver) if e.Value != nil { - doc.derefHeaders(e.Value.Headers, refNameResolver) - doc.derefContent(e.Value.Content, refNameResolver) + doc.derefHeaders(ctx, e.Value.Headers, refNameResolver) + doc.derefContent(ctx, e.Value.Content, refNameResolver) doc.derefLinks(e.Value.Links, refNameResolver) } } } -func (doc *T) derefParameter(p Parameter, refNameResolver RefNameResolver) { +func (doc *T) derefParameter(ctx context.Context, p Parameter, refNameResolver RefNameResolver) { doc.addSchemaToSpec(p.Schema, refNameResolver) - doc.derefContent(p.Content, refNameResolver) + doc.derefContent(ctx, p.Content, refNameResolver) if p.Schema != nil { - doc.derefSchema(p.Schema.Value, refNameResolver) + doc.derefSchema(ctx, p.Schema.Value, refNameResolver) } } -func (doc *T) derefRequestBody(r RequestBody, refNameResolver RefNameResolver) { - doc.derefContent(r.Content, refNameResolver) +func (doc *T) derefRequestBody(ctx context.Context, r RequestBody, refNameResolver RefNameResolver) { + doc.derefContent(ctx, r.Content, refNameResolver) } -func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameResolver) { +func (doc *T) derefPaths(ctx context.Context, paths map[string]*PathItem, refNameResolver RefNameResolver) { for _, ops := range paths { // inline full operations ops.Ref = "" @@ -293,19 +297,19 @@ func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameReso for _, op := range ops.Operations() { doc.addRequestBodyToSpec(op.RequestBody, refNameResolver) if op.RequestBody != nil && op.RequestBody.Value != nil { - doc.derefRequestBody(*op.RequestBody.Value, refNameResolver) + doc.derefRequestBody(ctx, *op.RequestBody.Value, refNameResolver) } for _, cb := range op.Callbacks { doc.addCallbackToSpec(cb, refNameResolver) if cb.Value != nil { - doc.derefPaths(*cb.Value, refNameResolver) + doc.derefPaths(ctx, *cb.Value, refNameResolver) } } - doc.derefResponses(op.Responses, refNameResolver) + doc.derefResponses(ctx, op.Responses, refNameResolver) for _, param := range op.Parameters { doc.addParameterToSpec(param, refNameResolver) if param.Value != nil { - doc.derefParameter(*param.Value, refNameResolver) + doc.derefParameter(ctx, *param.Value, refNameResolver) } } } @@ -324,6 +328,8 @@ func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameReso // // doc.InternalizeRefs(context.Background(), nil) func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref string) string) { + ctx = newVisited().withContext(ctx) + if refNameResolver == nil { refNameResolver = DefaultRefNameResolver } @@ -335,7 +341,7 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref stri doc.addSchemaToSpec(schema, refNameResolver) if schema != nil { schema.Ref = "" // always dereference the top level - doc.derefSchema(schema.Value, refNameResolver) + doc.derefSchema(ctx, schema.Value, refNameResolver) } } names = parametersMapNames(doc.Components.Parameters) @@ -344,18 +350,18 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref stri doc.addParameterToSpec(p, refNameResolver) if p != nil && p.Value != nil { p.Ref = "" // always dereference the top level - doc.derefParameter(*p.Value, refNameResolver) + doc.derefParameter(ctx, *p.Value, refNameResolver) } } - doc.derefHeaders(doc.Components.Headers, refNameResolver) + doc.derefHeaders(ctx, doc.Components.Headers, refNameResolver) for _, req := range doc.Components.RequestBodies { doc.addRequestBodyToSpec(req, refNameResolver) if req != nil && req.Value != nil { req.Ref = "" // always dereference the top level - doc.derefRequestBody(*req.Value, refNameResolver) + doc.derefRequestBody(ctx, *req.Value, refNameResolver) } } - doc.derefResponses(doc.Components.Responses, refNameResolver) + doc.derefResponses(ctx, doc.Components.Responses, refNameResolver) for _, ss := range doc.Components.SecuritySchemes { doc.addSecuritySchemeToSpec(ss, refNameResolver) } @@ -365,9 +371,9 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref stri doc.addCallbackToSpec(cb, refNameResolver) if cb != nil && cb.Value != nil { cb.Ref = "" // always dereference the top level - doc.derefPaths(*cb.Value, refNameResolver) + doc.derefPaths(ctx, *cb.Value, refNameResolver) } } - doc.derefPaths(doc.Paths, refNameResolver) + doc.derefPaths(ctx, doc.Paths, refNameResolver) } diff --git a/openapi3/testdata/recursiveRef/components/Cat.yml b/openapi3/testdata/recursiveRef/components/Cat.yml new file mode 100644 index 000000000..c476aa1a5 --- /dev/null +++ b/openapi3/testdata/recursiveRef/components/Cat.yml @@ -0,0 +1,4 @@ +type: object +properties: + cat: + $ref: ../openapi.yml#/components/schemas/Cat diff --git a/openapi3/testdata/recursiveRef/openapi.yml b/openapi3/testdata/recursiveRef/openapi.yml index 3559c8e85..675722a60 100644 --- a/openapi3/testdata/recursiveRef/openapi.yml +++ b/openapi3/testdata/recursiveRef/openapi.yml @@ -13,3 +13,5 @@ components: $ref: ./components/Foo/Foo2.yml Bar: $ref: ./components/Bar.yml + Cat: + $ref: ./components/Cat.yml diff --git a/openapi3/testdata/recursiveRef/openapi.yml.internalized.yml b/openapi3/testdata/recursiveRef/openapi.yml.internalized.yml index d1260eb14..073059025 100644 --- a/openapi3/testdata/recursiveRef/openapi.yml.internalized.yml +++ b/openapi3/testdata/recursiveRef/openapi.yml.internalized.yml @@ -29,6 +29,14 @@ } }, "type": "object" + }, + "Cat": { + "properties": { + "cat": { + "$ref": "#/components/schemas/Cat" + } + }, + "type": "object" } } }, diff --git a/openapi3/visited.go b/openapi3/visited.go new file mode 100644 index 000000000..38c7e8d69 --- /dev/null +++ b/openapi3/visited.go @@ -0,0 +1,81 @@ +package openapi3 + +import "context" + +func newVisited() *visitedComponent { + return &visitedComponent{ + header: make(map[*Header]struct{}), + schema: make(map[*Schema]struct{}), + } +} + +type visitedComponent struct { + header map[*Header]struct{} + schema map[*Schema]struct{} +} + +type ctxKey struct{} + +// withContext returns a copy of ctx with visitedComponent associated. If an instance +// of visitedComponent is already in the context, the context is not updated. +// +// Returned ctx can be passed to children function calls and used to check whether +// component already visited. For instance: +// +// ctx := context.Background() +// ctx = newVisited().withContext(ctx) +// ... +// doc.deferSchemaRecursively(ctx, schema) +// func (doc *T) deferSchemaRecursively(ctx context.Context, s *Schema) { +// if s == nil || isVisitedSchema(ctx, s) { +// return +// } +// } +func (v *visitedComponent) withContext(ctx context.Context) context.Context { + if visited, ok := ctx.Value(ctxKey{}).(*visitedComponent); ok { + if visited == v { + // Do not store the same object. + return ctx + } + } + + return context.WithValue(ctx, ctxKey{}, v) +} + +// visitedCtx returns the visitedComponent associated with the ctx. If no one +// is associated, a new visitedComponent is returned. +// +// The ctx should be initialized with method `withContext` first. +func visitedCtx(ctx context.Context) *visitedComponent { + if v, ok := ctx.Value(ctxKey{}).(*visitedComponent); ok { + return v + } + + return newVisited() +} + +// isVisitedHeader returns `true` if the *Header pointer was already visited +// otherwise it returns `false` +func isVisitedHeader(ctx context.Context, h *Header) bool { + visited := visitedCtx(ctx) + + if _, ok := visited.header[h]; ok { + return true + } + + visited.header[h] = struct{}{} + return false +} + +// isVisitedHeader returns `true` if the *Schema pointer was already visited +// otherwise it returns `false` +func isVisitedSchema(ctx context.Context, s *Schema) bool { + visited := visitedCtx(ctx) + + if _, ok := visited.schema[s]; ok { + return true + } + + visited.schema[s] = struct{}{} + return false +} From 0a3777d1ed9b0fa05ee92b67b57bf756b1e59dff Mon Sep 17 00:00:00 2001 From: Dmitriy Lukiyanchuk Date: Tue, 9 Aug 2022 09:14:44 +0300 Subject: [PATCH 2/4] Run go fmt by go1.19.0 --- openapi3/visited.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openapi3/visited.go b/openapi3/visited.go index 38c7e8d69..93708760c 100644 --- a/openapi3/visited.go +++ b/openapi3/visited.go @@ -22,15 +22,15 @@ type ctxKey struct{} // Returned ctx can be passed to children function calls and used to check whether // component already visited. For instance: // -// ctx := context.Background() -// ctx = newVisited().withContext(ctx) -// ... -// doc.deferSchemaRecursively(ctx, schema) -// func (doc *T) deferSchemaRecursively(ctx context.Context, s *Schema) { -// if s == nil || isVisitedSchema(ctx, s) { -// return -// } -// } +// ctx := context.Background() +// ctx = newVisited().withContext(ctx) +// ... +// doc.deferSchemaRecursively(ctx, schema) +// func (doc *T) deferSchemaRecursively(ctx context.Context, s *Schema) { +// if s == nil || isVisitedSchema(ctx, s) { +// return +// } +// } func (v *visitedComponent) withContext(ctx context.Context) context.Context { if visited, ok := ctx.Value(ctxKey{}).(*visitedComponent); ok { if visited == v { From 901a9ed14adf62d94175042971442530826c5fce Mon Sep 17 00:00:00 2001 From: Dmitriy Lukiyanchuk Date: Wed, 10 Aug 2022 18:33:34 +0300 Subject: [PATCH 3/4] Move openapi3 visitedComponent from context to doc *T --- openapi3/internalize_refs.go | 6 ++-- openapi3/openapi3.go | 2 ++ openapi3/visited.go | 62 +++++++----------------------------- 3 files changed, 17 insertions(+), 53 deletions(-) diff --git a/openapi3/internalize_refs.go b/openapi3/internalize_refs.go index 22aab397e..0afe5b0ff 100644 --- a/openapi3/internalize_refs.go +++ b/openapi3/internalize_refs.go @@ -200,7 +200,7 @@ func (doc *T) addCallbackToSpec(c *CallbackRef, refNameResolver RefNameResolver) } func (doc *T) derefSchema(ctx context.Context, s *Schema, refNameResolver RefNameResolver) { - if s == nil || isVisitedSchema(ctx, s) { + if s == nil || doc.isVisitedSchema(ctx, s) { return } @@ -230,7 +230,7 @@ func (doc *T) derefSchema(ctx context.Context, s *Schema, refNameResolver RefNam func (doc *T) derefHeaders(ctx context.Context, hs Headers, refNameResolver RefNameResolver) { for _, h := range hs { doc.addHeaderToSpec(h, refNameResolver) - if isVisitedHeader(ctx, h.Value) { + if doc.isVisitedHeader(ctx, h.Value) { continue } doc.derefParameter(ctx, h.Value.Parameter, refNameResolver) @@ -328,7 +328,7 @@ func (doc *T) derefPaths(ctx context.Context, paths map[string]*PathItem, refNam // // doc.InternalizeRefs(context.Background(), nil) func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref string) string) { - ctx = newVisited().withContext(ctx) + doc.resetVisited() if refNameResolver == nil { refNameResolver = DefaultRefNameResolver diff --git a/openapi3/openapi3.go b/openapi3/openapi3.go index c0188c25a..cb9183d47 100644 --- a/openapi3/openapi3.go +++ b/openapi3/openapi3.go @@ -21,6 +21,8 @@ type T struct { Servers Servers `json:"servers,omitempty" yaml:"servers,omitempty"` Tags Tags `json:"tags,omitempty" yaml:"tags,omitempty"` ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"` + + visited visitedComponent } // MarshalJSON returns the JSON encoding of T. diff --git a/openapi3/visited.go b/openapi3/visited.go index 93708760c..6dcf306a6 100644 --- a/openapi3/visited.go +++ b/openapi3/visited.go @@ -2,8 +2,8 @@ package openapi3 import "context" -func newVisited() *visitedComponent { - return &visitedComponent{ +func newVisited() visitedComponent { + return visitedComponent{ header: make(map[*Header]struct{}), schema: make(map[*Schema]struct{}), } @@ -14,68 +14,30 @@ type visitedComponent struct { schema map[*Schema]struct{} } -type ctxKey struct{} - -// withContext returns a copy of ctx with visitedComponent associated. If an instance -// of visitedComponent is already in the context, the context is not updated. -// -// Returned ctx can be passed to children function calls and used to check whether -// component already visited. For instance: -// -// ctx := context.Background() -// ctx = newVisited().withContext(ctx) -// ... -// doc.deferSchemaRecursively(ctx, schema) -// func (doc *T) deferSchemaRecursively(ctx context.Context, s *Schema) { -// if s == nil || isVisitedSchema(ctx, s) { -// return -// } -// } -func (v *visitedComponent) withContext(ctx context.Context) context.Context { - if visited, ok := ctx.Value(ctxKey{}).(*visitedComponent); ok { - if visited == v { - // Do not store the same object. - return ctx - } - } - - return context.WithValue(ctx, ctxKey{}, v) -} - -// visitedCtx returns the visitedComponent associated with the ctx. If no one -// is associated, a new visitedComponent is returned. -// -// The ctx should be initialized with method `withContext` first. -func visitedCtx(ctx context.Context) *visitedComponent { - if v, ok := ctx.Value(ctxKey{}).(*visitedComponent); ok { - return v - } - - return newVisited() +// resetVisited clears visitedComponent map +// should be called before recursion over doc *T +func (doc *T) resetVisited() { + doc.visited = newVisited() } // isVisitedHeader returns `true` if the *Header pointer was already visited // otherwise it returns `false` -func isVisitedHeader(ctx context.Context, h *Header) bool { - visited := visitedCtx(ctx) - - if _, ok := visited.header[h]; ok { +func (doc *T) isVisitedHeader(ctx context.Context, h *Header) bool { + if _, ok := doc.visited.header[h]; ok { return true } - visited.header[h] = struct{}{} + doc.visited.header[h] = struct{}{} return false } // isVisitedHeader returns `true` if the *Schema pointer was already visited // otherwise it returns `false` -func isVisitedSchema(ctx context.Context, s *Schema) bool { - visited := visitedCtx(ctx) - - if _, ok := visited.schema[s]; ok { +func (doc *T) isVisitedSchema(ctx context.Context, s *Schema) bool { + if _, ok := doc.visited.schema[s]; ok { return true } - visited.schema[s] = struct{}{} + doc.visited.schema[s] = struct{}{} return false } From 69c3063f588f8cc6cf110bc4546d1865d85822b7 Mon Sep 17 00:00:00 2001 From: Dmitriy Lukiyanchuk Date: Wed, 10 Aug 2022 18:37:45 +0300 Subject: [PATCH 4/4] Remove not used context from openapi3 --- openapi3/internalize_refs.go | 63 ++++++++++++++++++------------------ openapi3/visited.go | 6 ++-- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/openapi3/internalize_refs.go b/openapi3/internalize_refs.go index 0afe5b0ff..1733a495e 100644 --- a/openapi3/internalize_refs.go +++ b/openapi3/internalize_refs.go @@ -199,8 +199,8 @@ func (doc *T) addCallbackToSpec(c *CallbackRef, refNameResolver RefNameResolver) c.Ref = "#/components/callbacks/" + name } -func (doc *T) derefSchema(ctx context.Context, s *Schema, refNameResolver RefNameResolver) { - if s == nil || doc.isVisitedSchema(ctx, s) { +func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver) { + if s == nil || doc.isVisitedSchema(s) { return } @@ -208,32 +208,31 @@ func (doc *T) derefSchema(ctx context.Context, s *Schema, refNameResolver RefNam for _, s2 := range list { doc.addSchemaToSpec(s2, refNameResolver) if s2 != nil { - doc.derefSchema(ctx, s2.Value, refNameResolver) + doc.derefSchema(s2.Value, refNameResolver) } } } for _, s2 := range s.Properties { doc.addSchemaToSpec(s2, refNameResolver) - if s2 != nil { - doc.derefSchema(ctx, s2.Value, refNameResolver) + doc.derefSchema(s2.Value, refNameResolver) } } for _, ref := range []*SchemaRef{s.Not, s.AdditionalProperties, s.Items} { doc.addSchemaToSpec(ref, refNameResolver) if ref != nil { - doc.derefSchema(ctx, ref.Value, refNameResolver) + doc.derefSchema(ref.Value, refNameResolver) } } } -func (doc *T) derefHeaders(ctx context.Context, hs Headers, refNameResolver RefNameResolver) { +func (doc *T) derefHeaders(hs Headers, refNameResolver RefNameResolver) { for _, h := range hs { doc.addHeaderToSpec(h, refNameResolver) - if doc.isVisitedHeader(ctx, h.Value) { + if doc.isVisitedHeader(h.Value) { continue } - doc.derefParameter(ctx, h.Value.Parameter, refNameResolver) + doc.derefParameter(h.Value.Parameter, refNameResolver) } } @@ -243,15 +242,15 @@ func (doc *T) derefExamples(es Examples, refNameResolver RefNameResolver) { } } -func (doc *T) derefContent(ctx context.Context, c Content, refNameResolver RefNameResolver) { +func (doc *T) derefContent(c Content, refNameResolver RefNameResolver) { for _, mediatype := range c { doc.addSchemaToSpec(mediatype.Schema, refNameResolver) if mediatype.Schema != nil { - doc.derefSchema(ctx, mediatype.Schema.Value, refNameResolver) + doc.derefSchema(mediatype.Schema.Value, refNameResolver) } doc.derefExamples(mediatype.Examples, refNameResolver) for _, e := range mediatype.Encoding { - doc.derefHeaders(ctx, e.Headers, refNameResolver) + doc.derefHeaders(e.Headers, refNameResolver) } } } @@ -262,30 +261,30 @@ func (doc *T) derefLinks(ls Links, refNameResolver RefNameResolver) { } } -func (doc *T) derefResponses(ctx context.Context, es Responses, refNameResolver RefNameResolver) { +func (doc *T) derefResponses(es Responses, refNameResolver RefNameResolver) { for _, e := range es { doc.addResponseToSpec(e, refNameResolver) if e.Value != nil { - doc.derefHeaders(ctx, e.Value.Headers, refNameResolver) - doc.derefContent(ctx, e.Value.Content, refNameResolver) + doc.derefHeaders(e.Value.Headers, refNameResolver) + doc.derefContent(e.Value.Content, refNameResolver) doc.derefLinks(e.Value.Links, refNameResolver) } } } -func (doc *T) derefParameter(ctx context.Context, p Parameter, refNameResolver RefNameResolver) { +func (doc *T) derefParameter(p Parameter, refNameResolver RefNameResolver) { doc.addSchemaToSpec(p.Schema, refNameResolver) - doc.derefContent(ctx, p.Content, refNameResolver) + doc.derefContent(p.Content, refNameResolver) if p.Schema != nil { - doc.derefSchema(ctx, p.Schema.Value, refNameResolver) + doc.derefSchema(p.Schema.Value, refNameResolver) } } -func (doc *T) derefRequestBody(ctx context.Context, r RequestBody, refNameResolver RefNameResolver) { - doc.derefContent(ctx, r.Content, refNameResolver) +func (doc *T) derefRequestBody(r RequestBody, refNameResolver RefNameResolver) { + doc.derefContent(r.Content, refNameResolver) } -func (doc *T) derefPaths(ctx context.Context, paths map[string]*PathItem, refNameResolver RefNameResolver) { +func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameResolver) { for _, ops := range paths { // inline full operations ops.Ref = "" @@ -297,19 +296,19 @@ func (doc *T) derefPaths(ctx context.Context, paths map[string]*PathItem, refNam for _, op := range ops.Operations() { doc.addRequestBodyToSpec(op.RequestBody, refNameResolver) if op.RequestBody != nil && op.RequestBody.Value != nil { - doc.derefRequestBody(ctx, *op.RequestBody.Value, refNameResolver) + doc.derefRequestBody(*op.RequestBody.Value, refNameResolver) } for _, cb := range op.Callbacks { doc.addCallbackToSpec(cb, refNameResolver) if cb.Value != nil { - doc.derefPaths(ctx, *cb.Value, refNameResolver) + doc.derefPaths(*cb.Value, refNameResolver) } } - doc.derefResponses(ctx, op.Responses, refNameResolver) + doc.derefResponses(op.Responses, refNameResolver) for _, param := range op.Parameters { doc.addParameterToSpec(param, refNameResolver) if param.Value != nil { - doc.derefParameter(ctx, *param.Value, refNameResolver) + doc.derefParameter(*param.Value, refNameResolver) } } } @@ -341,7 +340,7 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref stri doc.addSchemaToSpec(schema, refNameResolver) if schema != nil { schema.Ref = "" // always dereference the top level - doc.derefSchema(ctx, schema.Value, refNameResolver) + doc.derefSchema(schema.Value, refNameResolver) } } names = parametersMapNames(doc.Components.Parameters) @@ -350,18 +349,18 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref stri doc.addParameterToSpec(p, refNameResolver) if p != nil && p.Value != nil { p.Ref = "" // always dereference the top level - doc.derefParameter(ctx, *p.Value, refNameResolver) + doc.derefParameter(*p.Value, refNameResolver) } } - doc.derefHeaders(ctx, doc.Components.Headers, refNameResolver) + doc.derefHeaders(doc.Components.Headers, refNameResolver) for _, req := range doc.Components.RequestBodies { doc.addRequestBodyToSpec(req, refNameResolver) if req != nil && req.Value != nil { req.Ref = "" // always dereference the top level - doc.derefRequestBody(ctx, *req.Value, refNameResolver) + doc.derefRequestBody(*req.Value, refNameResolver) } } - doc.derefResponses(ctx, doc.Components.Responses, refNameResolver) + doc.derefResponses(doc.Components.Responses, refNameResolver) for _, ss := range doc.Components.SecuritySchemes { doc.addSecuritySchemeToSpec(ss, refNameResolver) } @@ -371,9 +370,9 @@ func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref stri doc.addCallbackToSpec(cb, refNameResolver) if cb != nil && cb.Value != nil { cb.Ref = "" // always dereference the top level - doc.derefPaths(ctx, *cb.Value, refNameResolver) + doc.derefPaths(*cb.Value, refNameResolver) } } - doc.derefPaths(ctx, doc.Paths, refNameResolver) + doc.derefPaths(doc.Paths, refNameResolver) } diff --git a/openapi3/visited.go b/openapi3/visited.go index 6dcf306a6..67f970e36 100644 --- a/openapi3/visited.go +++ b/openapi3/visited.go @@ -1,7 +1,5 @@ package openapi3 -import "context" - func newVisited() visitedComponent { return visitedComponent{ header: make(map[*Header]struct{}), @@ -22,7 +20,7 @@ func (doc *T) resetVisited() { // isVisitedHeader returns `true` if the *Header pointer was already visited // otherwise it returns `false` -func (doc *T) isVisitedHeader(ctx context.Context, h *Header) bool { +func (doc *T) isVisitedHeader(h *Header) bool { if _, ok := doc.visited.header[h]; ok { return true } @@ -33,7 +31,7 @@ func (doc *T) isVisitedHeader(ctx context.Context, h *Header) bool { // isVisitedHeader returns `true` if the *Schema pointer was already visited // otherwise it returns `false` -func (doc *T) isVisitedSchema(ctx context.Context, s *Schema) bool { +func (doc *T) isVisitedSchema(s *Schema) bool { if _, ok := doc.visited.schema[s]; ok { return true }