Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openapi3: implement circular reference backtracking #970

Merged
merged 6 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/docs/openapi3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ var (
// ErrSchemaInputInf may be returned when validating a number
ErrSchemaInputInf = errors.New("floating point Inf is not allowed")
)
var CircularReferenceCounter = 3
var CircularReferenceError = "kin-openapi bug found: circular schema reference not handled"
var DefaultReadFromURI = URIMapCache(ReadFromURIs(ReadFromHTTP(http.DefaultClient), ReadFromFile))
DefaultReadFromURI returns a caching ReadFromURIFunc which can read remote
HTTP URIs and local file URIs.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ for _, path := range doc.Paths.InMatchingOrder() {

## CHANGELOG: Sub-v1 breaking API changes

### v0.126.0
* `openapi3.CircularReferenceError` and `openapi3.CircularReferenceCounter` are removed. `openapi3.Loader` now implements reference backtracking, so any kind of circular references should be properly resolved.

### v0.125.0
* The `openapi3filter.ErrFunc` and `openapi3filter.LogFunc` func types now take the validated request's context as first argument.

Expand Down
9 changes: 0 additions & 9 deletions cmd/validate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ import (
"github.com/getkin/kin-openapi/openapi3"
)

var (
defaultCircular = openapi3.CircularReferenceCounter
circular = flag.Int("circular", defaultCircular, "bump this (upper) limit when there's trouble with cyclic schema references")
)

var (
defaultDefaults = true
defaults = flag.Bool("defaults", defaultDefaults, "when false, disables schemas' default field validation")
Expand Down Expand Up @@ -59,7 +54,6 @@ func main() {

switch {
case vd.OpenAPI == "3" || strings.HasPrefix(vd.OpenAPI, "3."):
openapi3.CircularReferenceCounter = *circular
loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = *ext

Expand Down Expand Up @@ -90,9 +84,6 @@ func main() {

case vd.OpenAPI == "2" || strings.HasPrefix(vd.OpenAPI, "2."),
vd.Swagger == "2" || strings.HasPrefix(vd.Swagger, "2."):
if *circular != defaultCircular {
log.Fatal("Flag --circular is only for OpenAPIv3")
}
if *defaults != defaultDefaults {
log.Fatal("Flag --defaults is only for OpenAPIv3")
}
Expand Down
2 changes: 1 addition & 1 deletion openapi3/issue570_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import (
func TestIssue570(t *testing.T) {
loader := NewLoader()
_, err := loader.LoadFromFile("testdata/issue570.json")
require.ErrorContains(t, err, CircularReferenceError)
require.NoError(t, err)
}
15 changes: 0 additions & 15 deletions openapi3/issue615_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,6 @@ import (
)

func TestIssue615(t *testing.T) {
{
var old int
old, openapi3.CircularReferenceCounter = openapi3.CircularReferenceCounter, 1
defer func() { openapi3.CircularReferenceCounter = old }()

loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true
_, err := loader.LoadFromFile("testdata/recursiveRef/issue615.yml")
require.ErrorContains(t, err, openapi3.CircularReferenceError)
}

var old int
old, openapi3.CircularReferenceCounter = openapi3.CircularReferenceCounter, 4
defer func() { openapi3.CircularReferenceCounter = old }()

loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true
doc, err := loader.LoadFromFile("testdata/recursiveRef/issue615.yml")
Expand Down
5 changes: 0 additions & 5 deletions openapi3/issue796_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ import (
)

func TestIssue796(t *testing.T) {
var old int
// Need to set CircularReferenceCounter to > 10
old, CircularReferenceCounter = CircularReferenceCounter, 20
defer func() { CircularReferenceCounter = old }()

loader := NewLoader()
doc, err := loader.LoadFromFile("testdata/issue796.yml")
require.NoError(t, err)
Expand Down
14 changes: 14 additions & 0 deletions openapi3/load_cicular_ref_with_external_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ func TestLoadCircularRefFromFile(t *testing.T) {
bar.Value.Properties["foo"] = &openapi3.SchemaRef{Ref: "#/components/schemas/Foo", Value: foo.Value}
foo.Value.Properties["bar"] = &openapi3.SchemaRef{Ref: "#/components/schemas/Bar", Value: bar.Value}

bazNestedRef := &openapi3.SchemaRef{Ref: "./baz.yml#/BazNested"}
array := openapi3.NewArraySchema()
array.Items = bazNestedRef
bazNested := &openapi3.Schema{Properties: map[string]*openapi3.SchemaRef{
"bazArray": {
Value: &openapi3.Schema{
Items: bazNestedRef,
},
},
"baz": bazNestedRef,
}}
bazNestedRef.Value = bazNested

want := &openapi3.T{
OpenAPI: "3.0.3",
Info: &openapi3.Info{
Expand All @@ -57,6 +70,7 @@ func TestLoadCircularRefFromFile(t *testing.T) {
Schemas: openapi3.Schemas{
"Foo": foo,
"Bar": bar,
"Baz": bazNestedRef,
},
},
}
Expand Down
Loading
Loading