Skip to content

Commit 582e6d0

Browse files
authored
openapi3: handle refs missing fragment (#511)
1 parent bd3ac0e commit 582e6d0

File tree

3 files changed

+301
-1
lines changed

3 files changed

+301
-1
lines changed

openapi3/issue495_test.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package openapi3
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestIssue495(t *testing.T) {
10+
{
11+
spec := []byte(`
12+
openapi: 3.0.1
13+
info:
14+
version: v1
15+
title: Products api
16+
components:
17+
schemas:
18+
someSchema:
19+
type: object
20+
schemaArray:
21+
type: array
22+
minItems: 1
23+
items:
24+
$ref: '#'
25+
paths:
26+
/categories:
27+
get:
28+
responses:
29+
'200':
30+
description: ''
31+
content:
32+
application/json:
33+
schema:
34+
properties:
35+
allOf:
36+
$ref: '#/components/schemas/schemaArray'
37+
`[1:])
38+
39+
sl := NewLoader()
40+
41+
doc, err := sl.LoadFromData(spec)
42+
require.NoError(t, err)
43+
44+
err = doc.Validate(sl.Context)
45+
require.EqualError(t, err, `invalid components: schema "schemaArray": found unresolved ref: "#"`)
46+
}
47+
48+
spec := []byte(`
49+
openapi: 3.0.1
50+
info:
51+
version: v1
52+
title: Products api
53+
components:
54+
schemas:
55+
someSchema:
56+
type: object
57+
schemaArray:
58+
type: array
59+
minItems: 1
60+
items:
61+
$ref: '#/components/schemas/someSchema'
62+
paths:
63+
/categories:
64+
get:
65+
responses:
66+
'200':
67+
description: ''
68+
content:
69+
application/json:
70+
schema:
71+
properties:
72+
allOf:
73+
$ref: '#/components/schemas/schemaArray'
74+
`[1:])
75+
76+
sl := NewLoader()
77+
78+
doc, err := sl.LoadFromData(spec)
79+
require.NoError(t, err)
80+
81+
err = doc.Validate(sl.Context)
82+
require.NoError(t, err)
83+
84+
require.Equal(t, &Schema{Type: "object"}, doc.Components.Schemas["schemaArray"].Value.Items.Value)
85+
}
86+
87+
func TestIssue495WithDraft04(t *testing.T) {
88+
spec := []byte(`
89+
openapi: 3.0.1
90+
servers:
91+
- url: http://localhost:5000
92+
info:
93+
version: v1
94+
title: Products api
95+
contact:
96+
name: me
97+
98+
description: This is a sample
99+
paths:
100+
/categories:
101+
get:
102+
summary: Provides the available categories for the store
103+
operationId: list-categories
104+
responses:
105+
'200':
106+
description: this is a desc
107+
content:
108+
application/json:
109+
schema:
110+
$ref: http://json-schema.org/draft-04/schema
111+
`[1:])
112+
113+
sl := NewLoader()
114+
sl.IsExternalRefsAllowed = true
115+
116+
doc, err := sl.LoadFromData(spec)
117+
require.NoError(t, err)
118+
119+
err = doc.Validate(sl.Context)
120+
require.ErrorContains(t, err, `found unresolved ref: "#"`)
121+
}
122+
123+
func TestIssue495WithDraft04Bis(t *testing.T) {
124+
spec := []byte(`
125+
openapi: 3.0.1
126+
servers:
127+
- url: http://localhost:5000
128+
info:
129+
version: v1
130+
title: Products api
131+
contact:
132+
name: me
133+
134+
description: This is a sample
135+
paths:
136+
/categories:
137+
get:
138+
summary: Provides the available categories for the store
139+
operationId: list-categories
140+
responses:
141+
'200':
142+
description: this is a desc
143+
content:
144+
application/json:
145+
schema:
146+
$ref: testdata/draft04.yml
147+
`[1:])
148+
149+
sl := NewLoader()
150+
sl.IsExternalRefsAllowed = true
151+
152+
doc, err := sl.LoadFromData(spec)
153+
require.NoError(t, err)
154+
155+
err = doc.Validate(sl.Context)
156+
require.ErrorContains(t, err, `found unresolved ref: "#"`)
157+
}

openapi3/loader.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,10 @@ func (loader *Loader) resolveComponent(doc *T, ref string, path *url.URL, resolv
310310
return nil, nil, fmt.Errorf("cannot parse reference: %q: %v", ref, parsedURL)
311311
}
312312
fragment := parsedURL.Fragment
313-
if !strings.HasPrefix(fragment, "/") {
313+
if fragment == "" {
314+
fragment = "/"
315+
}
316+
if fragment[0] != '/' {
314317
return nil, nil, fmt.Errorf("expected fragment prefix '#/' in URI %q", ref)
315318
}
316319

openapi3/testdata/draft04.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
id: http://json-schema.org/draft-04/schema#
2+
$schema: http://json-schema.org/draft-04/schema#
3+
description: Core schema meta-schema
4+
definitions:
5+
schemaArray:
6+
type: array
7+
minItems: 1
8+
items:
9+
$ref: '#'
10+
positiveInteger:
11+
type: integer
12+
minimum: 0
13+
positiveIntegerDefault0:
14+
allOf:
15+
- $ref: '#/definitions/positiveInteger'
16+
- default: 0
17+
simpleTypes:
18+
enum:
19+
- array
20+
- boolean
21+
- integer
22+
- 'null'
23+
- number
24+
- object
25+
- string
26+
stringArray:
27+
type: array
28+
items:
29+
type: string
30+
minItems: 1
31+
uniqueItems: true
32+
type: object
33+
properties:
34+
id:
35+
type: string
36+
$schema:
37+
type: string
38+
title:
39+
type: string
40+
description:
41+
type: string
42+
default: {}
43+
multipleOf:
44+
type: number
45+
minimum: 0
46+
exclusiveMinimum: true
47+
maximum:
48+
type: number
49+
exclusiveMaximum:
50+
type: boolean
51+
default: false
52+
minimum:
53+
type: number
54+
exclusiveMinimum:
55+
type: boolean
56+
default: false
57+
maxLength:
58+
$ref: '#/definitions/positiveInteger'
59+
minLength:
60+
$ref: '#/definitions/positiveIntegerDefault0'
61+
pattern:
62+
type: string
63+
format: regex
64+
additionalItems:
65+
anyOf:
66+
- type: boolean
67+
- $ref: '#'
68+
default: {}
69+
items:
70+
anyOf:
71+
- $ref: '#'
72+
- $ref: '#/definitions/schemaArray'
73+
default: {}
74+
maxItems:
75+
$ref: '#/definitions/positiveInteger'
76+
minItems:
77+
$ref: '#/definitions/positiveIntegerDefault0'
78+
uniqueItems:
79+
type: boolean
80+
default: false
81+
maxProperties:
82+
$ref: '#/definitions/positiveInteger'
83+
minProperties:
84+
$ref: '#/definitions/positiveIntegerDefault0'
85+
required:
86+
$ref: '#/definitions/stringArray'
87+
additionalProperties:
88+
anyOf:
89+
- type: boolean
90+
- $ref: '#'
91+
default: {}
92+
definitions:
93+
type: object
94+
additionalProperties:
95+
$ref: '#'
96+
default: {}
97+
properties:
98+
type: object
99+
additionalProperties:
100+
$ref: '#'
101+
default: {}
102+
patternProperties:
103+
type: object
104+
additionalProperties:
105+
'$ref': '#'
106+
default: {}
107+
dependencies:
108+
type: object
109+
additionalProperties:
110+
anyOf:
111+
- $ref: '#'
112+
- $ref: '#/definitions/stringArray'
113+
enum:
114+
type: array
115+
minItems: 1
116+
uniqueItems: true
117+
type:
118+
anyOf:
119+
- $ref: '#/definitions/simpleTypes'
120+
- type: array
121+
items:
122+
$ref: '#/definitions/simpleTypes'
123+
minItems: 1
124+
uniqueItems: true
125+
format:
126+
type: string
127+
allOf:
128+
$ref: '#/definitions/schemaArray'
129+
anyOf:
130+
$ref: '#/definitions/schemaArray'
131+
oneOf:
132+
$ref: '#/definitions/schemaArray'
133+
not:
134+
$ref: '#'
135+
dependencies:
136+
exclusiveMaximum:
137+
- maximum
138+
exclusiveMinimum:
139+
- minimum
140+
default: {}

0 commit comments

Comments
 (0)