Skip to content

Commit 68a9c97

Browse files
committed
feat: support OAS 2.0
Some users have aep-compliant schemas, but OAS 2.0 descriptions. This is especially common for translation gateways like grpc-gateway (which currently only supports 2.0). Fixes #10.
1 parent c50f4be commit 68a9c97

3 files changed

Lines changed: 54 additions & 7 deletions

File tree

internal/openapi/openapi.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ type Parameter struct {
6363
type Response struct {
6464
Description string `json:"description"`
6565
Content map[string]MediaType `json:"content"`
66+
// oas 2.0 has the schema in the response.
67+
Schema *Schema `json:"schema,omitempty"`
6668
}
6769

6870
type RequestBody struct {

internal/service/service_definition.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type ServiceDefinition struct {
1919

2020
func GetServiceDefinition(api *openapi.OpenAPI, pathPrefix string) (*ServiceDefinition, error) {
2121
slog.Debug("parsing openapi", "pathPrefix", pathPrefix)
22+
oasVersion := api.Info.Version
2223
resourceBySingular := make(map[string]*Resource)
2324
// we try to parse the paths to find possible resources, since
2425
// they may not always be annotated as such.
@@ -40,15 +41,13 @@ func GetServiceDefinition(api *openapi.OpenAPI, pathPrefix string) (*ServiceDefi
4041
}
4142
if pathItem.Get != nil {
4243
if resp, ok := pathItem.Get.Responses["200"]; ok {
43-
ct := resp.Content[contentType]
44-
sRef = ct.Schema
44+
sRef = getSchemaFromResponse(resp, oasVersion)
4545
r.GetMethod = &GetMethod{}
4646
}
4747
}
4848
if pathItem.Patch != nil {
4949
if resp, ok := pathItem.Patch.Responses["200"]; ok {
50-
ct := resp.Content[contentType]
51-
sRef = ct.Schema
50+
sRef = getSchemaFromResponse(resp, oasVersion)
5251
r.UpdateMethod = &UpdateMethod{}
5352
}
5453
}
@@ -57,8 +56,7 @@ func GetServiceDefinition(api *openapi.OpenAPI, pathPrefix string) (*ServiceDefi
5756
if pathItem.Post != nil {
5857
// check if there is a query parameter "id"
5958
if resp, ok := pathItem.Post.Responses["200"]; ok {
60-
ct := resp.Content[contentType]
61-
sRef = ct.Schema
59+
sRef = getSchemaFromResponse(resp, oasVersion)
6260
supportsUserSettableCreate := false
6361
for _, param := range pathItem.Post.Parameters {
6462
if param.Name == "id" {
@@ -73,7 +71,8 @@ func GetServiceDefinition(api *openapi.OpenAPI, pathPrefix string) (*ServiceDefi
7371
if pathItem.Get != nil {
7472
if resp, ok := pathItem.Get.Responses["200"]; ok {
7573
ct := resp.Content[contentType]
76-
resolvedSchema, err := dereferencedSchema(*ct.Schema, api)
74+
respSchema := getSchemaFromResponse(resp, oasVersion)
75+
resolvedSchema, err := dereferencedSchema(*respSchema, api)
7776
if err != nil {
7877
return nil, fmt.Errorf("error dereferencing schema %q: %v", ct.Schema.Ref, err)
7978
}
@@ -237,3 +236,13 @@ func dereferencedSchema(schema openapi.Schema, api *openapi.OpenAPI) (*openapi.S
237236
}
238237
return &schema, nil
239238
}
239+
240+
func getSchemaFromResponse(r openapi.Response, oasVersion string) *openapi.Schema {
241+
switch oasVersion {
242+
case "2.0":
243+
return r.Schema
244+
default:
245+
ct := r.Content[contentType]
246+
return ct.Schema
247+
}
248+
}

internal/service/service_definition_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,42 @@ func TestGetServiceDefinition(t *testing.T) {
202202
"should support user-settable create")
203203
},
204204
},
205+
{
206+
name: "OAS 2.0 style schema in response",
207+
api: &openapi.OpenAPI{
208+
Info: openapi.Info{Version: "2.0"},
209+
Servers: []openapi.Server{{URL: "https://api.example.com"}},
210+
Paths: map[string]openapi.PathItem{
211+
"/widgets/{widget}": {
212+
Get: &openapi.Operation{
213+
Responses: map[string]openapi.Response{
214+
"200": {
215+
Schema: &openapi.Schema{
216+
Ref: "#/components/schemas/Widget",
217+
},
218+
},
219+
},
220+
},
221+
},
222+
},
223+
Components: openapi.Components{
224+
Schemas: map[string]openapi.Schema{
225+
"Widget": {
226+
Type: "object",
227+
Properties: map[string]openapi.Schema{
228+
"name": {Type: "string"},
229+
},
230+
},
231+
},
232+
},
233+
},
234+
validateResult: func(t *testing.T, sd *ServiceDefinition) {
235+
widget, ok := sd.Resources["widget"]
236+
assert.True(t, ok, "widget resource should exist")
237+
assert.NotNil(t, widget.GetMethod, "should have GET method")
238+
assert.Equal(t, []string{"widgets", "{widget}"}, widget.Pattern)
239+
},
240+
},
205241
}
206242

207243
for _, tt := range tests {

0 commit comments

Comments
 (0)