Skip to content

Commit

Permalink
Merge pull request #551 from tdakkota/fix/parser-use-refKey
Browse files Browse the repository at this point in the history
fix(parser): use `RefKey` as cache key for components
  • Loading branch information
ernado authored Sep 5, 2022
2 parents 157e019 + e00c941 commit 7c5619c
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 54 deletions.
2 changes: 1 addition & 1 deletion openapi/parser/parse_security.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (p *parser) parseSecurityRequirements(
locator := locator.Index(idx)

for name, scopes := range req {
v, ok := p.refs.securitySchemes[name]
v, ok := p.securitySchemes[name]
if !ok {
err := errors.Errorf("unknown security schema %q", name)
return nil, p.wrapLocation(ctx.LastLoc(), locator.Key(name), err)
Expand Down
51 changes: 28 additions & 23 deletions openapi/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/ogen-go/ogen/openapi"
)

type refKey = jsonpointer.RefKey

type parser struct {
// api spec, immutable.
spec *ogen.Spec
Expand All @@ -23,14 +25,16 @@ type parser struct {
operations []*openapi.Operation
// refs contains lazy-initialized referenced components.
refs struct {
requestBodies map[string]*openapi.RequestBody
responses map[string]*openapi.Response
parameters map[string]*openapi.Parameter
headers map[string]*openapi.Header
examples map[string]*openapi.Example
securitySchemes map[string]*ogen.SecurityScheme
pathItems map[string]pathItem
requestBodies map[refKey]*openapi.RequestBody
responses map[refKey]*openapi.Response
parameters map[refKey]*openapi.Parameter
headers map[refKey]*openapi.Header
examples map[refKey]*openapi.Example
securitySchemes map[refKey]*ogen.SecurityScheme
pathItems map[refKey]pathItem
}
// securitySchemes contains security schemes defined in the root spec.
securitySchemes map[string]*ogen.SecurityScheme

external jsonschema.ExternalResolver
schemas map[string]*yaml.Node
Expand All @@ -52,23 +56,24 @@ func Parse(spec *ogen.Spec, s Settings) (*openapi.API, error) {
spec: spec,
operations: nil,
refs: struct {
requestBodies map[string]*openapi.RequestBody
responses map[string]*openapi.Response
parameters map[string]*openapi.Parameter
headers map[string]*openapi.Header
examples map[string]*openapi.Example
securitySchemes map[string]*ogen.SecurityScheme
pathItems map[string]pathItem
requestBodies map[refKey]*openapi.RequestBody
responses map[refKey]*openapi.Response
parameters map[refKey]*openapi.Parameter
headers map[refKey]*openapi.Header
examples map[refKey]*openapi.Example
securitySchemes map[refKey]*ogen.SecurityScheme
pathItems map[refKey]pathItem
}{
requestBodies: map[string]*openapi.RequestBody{},
responses: map[string]*openapi.Response{},
parameters: map[string]*openapi.Parameter{},
headers: map[string]*openapi.Header{},
examples: map[string]*openapi.Example{},
securitySchemes: map[string]*ogen.SecurityScheme{},
pathItems: map[string]pathItem{},
requestBodies: map[refKey]*openapi.RequestBody{},
responses: map[refKey]*openapi.Response{},
parameters: map[refKey]*openapi.Parameter{},
headers: map[refKey]*openapi.Header{},
examples: map[refKey]*openapi.Example{},
securitySchemes: map[refKey]*ogen.SecurityScheme{},
pathItems: map[refKey]pathItem{},
},
external: s.External,
securitySchemes: map[string]*ogen.SecurityScheme{},
external: s.External,
schemas: map[string]*yaml.Node{
"": spec.Raw,
},
Expand All @@ -91,7 +96,7 @@ func Parse(spec *ogen.Spec, s Settings) (*openapi.API, error) {
}

for name, s := range spec.Components.SecuritySchemes {
p.refs.securitySchemes[name] = s
p.securitySchemes[name] = s
}

components, err := p.parseComponents(spec.Components)
Expand Down
86 changes: 57 additions & 29 deletions openapi/parser/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,16 @@ func (p *parser) resolve(key jsonpointer.RefKey, ctx *jsonpointer.ResolveCtx, to
func (p *parser) resolveRequestBody(ref string, ctx *jsonpointer.ResolveCtx) (*openapi.RequestBody, error) {
const prefix = "#/components/requestBodies/"

if r, ok := p.refs.requestBodies[ref]; ok {
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

if r, ok := p.refs.requestBodies[key]; ok {
return r, nil
}

key, err := ctx.Add(ref)
if err != nil {
if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -94,19 +98,23 @@ func (p *parser) resolveRequestBody(ref string, ctx *jsonpointer.ResolveCtx) (*o
}

r.Ref = ref
p.refs.requestBodies[ref] = r
p.refs.requestBodies[key] = r
return r, nil
}

func (p *parser) resolveResponse(ref string, ctx *jsonpointer.ResolveCtx) (*openapi.Response, error) {
const prefix = "#/components/responses/"

if r, ok := p.refs.responses[ref]; ok {
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

if r, ok := p.refs.responses[key]; ok {
return r, nil
}

key, err := ctx.Add(ref)
if err != nil {
if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -136,19 +144,23 @@ func (p *parser) resolveResponse(ref string, ctx *jsonpointer.ResolveCtx) (*open
}

r.Ref = ref
p.refs.responses[ref] = r
p.refs.responses[key] = r
return r, nil
}

func (p *parser) resolveParameter(ref string, ctx *jsonpointer.ResolveCtx) (*openapi.Parameter, error) {
const prefix = "#/components/parameters/"

if param, ok := p.refs.parameters[ref]; ok {
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

if param, ok := p.refs.parameters[key]; ok {
return param, nil
}

key, err := ctx.Add(ref)
if err != nil {
if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -178,19 +190,23 @@ func (p *parser) resolveParameter(ref string, ctx *jsonpointer.ResolveCtx) (*ope
}

param.Ref = ref
p.refs.parameters[ref] = param
p.refs.parameters[key] = param
return param, nil
}

func (p *parser) resolveHeader(headerName, ref string, ctx *jsonpointer.ResolveCtx) (*openapi.Header, error) {
const prefix = "#/components/headers/"

if header, ok := p.refs.headers[ref]; ok {
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

if header, ok := p.refs.headers[key]; ok {
return header, nil
}

key, err := ctx.Add(ref)
if err != nil {
if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -220,19 +236,23 @@ func (p *parser) resolveHeader(headerName, ref string, ctx *jsonpointer.ResolveC
}

header.Ref = ref
p.refs.headers[ref] = header
p.refs.headers[key] = header
return header, nil
}

func (p *parser) resolveExample(ref string, ctx *jsonpointer.ResolveCtx) (*openapi.Example, error) {
const prefix = "#/components/examples/"

if ex, ok := p.refs.examples[ref]; ok {
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

if ex, ok := p.refs.examples[key]; ok {
return ex, nil
}

key, err := ctx.Add(ref)
if err != nil {
if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -264,19 +284,23 @@ func (p *parser) resolveExample(ref string, ctx *jsonpointer.ResolveCtx) (*opena
if ex != nil {
ex.Ref = ref
}
p.refs.examples[ref] = ex
p.refs.examples[key] = ex
return ex, nil
}

func (p *parser) resolveSecurityScheme(ref string, ctx *jsonpointer.ResolveCtx) (*ogen.SecurityScheme, error) {
const prefix = "#/components/securitySchemes/"

if r, ok := p.refs.securitySchemes[ref]; ok {
return r, nil
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

key, err := ctx.Add(ref)
if err != nil {
if s, ok := p.refs.securitySchemes[key]; ok {
return s, nil
}

if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -305,7 +329,7 @@ func (p *parser) resolveSecurityScheme(ref string, ctx *jsonpointer.ResolveCtx)
return nil, err
}

p.refs.securitySchemes[ref] = ss
p.refs.securitySchemes[key] = ss
return ss, nil
}

Expand All @@ -316,12 +340,16 @@ func (p *parser) resolvePathItem(
) (pathItem, error) {
const prefix = "#/components/pathItems/"

if r, ok := p.refs.pathItems[ref]; ok {
key, err := ctx.Key(ref)
if err != nil {
return nil, err
}

if r, ok := p.refs.pathItems[key]; ok {
return r, nil
}

key, err := ctx.Add(ref)
if err != nil {
if err := ctx.AddKey(key); err != nil {
return nil, err
}
defer func() {
Expand Down Expand Up @@ -350,6 +378,6 @@ func (p *parser) resolvePathItem(
return nil, err
}

p.refs.pathItems[ref] = r
p.refs.pathItems[key] = r
return r, nil
}
2 changes: 1 addition & 1 deletion openapi/parser/resolve_external_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func TestExternalReference(t *testing.T) {
Schema: schema,
Examples: map[string]*openapi.Example{
"ref": {
Ref: "#/components/examples/RemoteExample",
Ref: "#/components/examples/LocalExample",
Value: exampleValue,
},
},
Expand Down

0 comments on commit 7c5619c

Please sign in to comment.