Skip to content

Commit

Permalink
Support loading documents with filepath.FromSlash (#251)
Browse files Browse the repository at this point in the history
  • Loading branch information
fenollp committed Apr 23, 2021
1 parent 8407517 commit a4e36cd
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 16 deletions.
33 changes: 17 additions & 16 deletions openapi3/swagger_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"net/url"
"path"
"path/filepath"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -64,8 +65,8 @@ func (swaggerLoader *SwaggerLoader) LoadSwaggerFromURI(location *url.URL) (*Swag
}

// LoadSwaggerFromFile loads a spec from a local file path
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromFile(path string) (*Swagger, error) {
return swaggerLoader.LoadSwaggerFromURI(&url.URL{Path: path})
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromFile(location string) (*Swagger, error) {
return swaggerLoader.LoadSwaggerFromURI(&url.URL{Path: filepath.ToSlash(location)})
}

func (swaggerLoader *SwaggerLoader) loadSwaggerFromURIInternal(location *url.URL) (*Swagger, error) {
Expand Down Expand Up @@ -150,16 +151,16 @@ func (swaggerLoader *SwaggerLoader) LoadSwaggerFromData(data []byte) (*Swagger,

// LoadSwaggerFromDataWithPath takes the OpenApi spec data in bytes and a path where the resolver can find referred
// elements and returns a *Swagger with all resolved data or an error if unable to load data or resolve refs.
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromDataWithPath(data []byte, path *url.URL) (*Swagger, error) {
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromDataWithPath(data []byte, location *url.URL) (*Swagger, error) {
swaggerLoader.resetVisitedPathItemRefs()
return swaggerLoader.loadSwaggerFromDataWithPathInternal(data, path)
return swaggerLoader.loadSwaggerFromDataWithPathInternal(data, location)
}

func (swaggerLoader *SwaggerLoader) loadSwaggerFromDataWithPathInternal(data []byte, path *url.URL) (*Swagger, error) {
func (swaggerLoader *SwaggerLoader) loadSwaggerFromDataWithPathInternal(data []byte, location *url.URL) (*Swagger, error) {
if swaggerLoader.visitedDocuments == nil {
swaggerLoader.visitedDocuments = make(map[string]*Swagger)
}
uri := path.String()
uri := location.String()
if doc, ok := swaggerLoader.visitedDocuments[uri]; ok {
return doc, nil
}
Expand All @@ -170,53 +171,53 @@ func (swaggerLoader *SwaggerLoader) loadSwaggerFromDataWithPathInternal(data []b
if err := yaml.Unmarshal(data, swagger); err != nil {
return nil, err
}
if err := swaggerLoader.ResolveRefsIn(swagger, path); err != nil {
if err := swaggerLoader.ResolveRefsIn(swagger, location); err != nil {
return nil, err
}

return swagger, nil
}

// ResolveRefsIn expands references if for instance spec was just unmarshalled
func (swaggerLoader *SwaggerLoader) ResolveRefsIn(swagger *Swagger, path *url.URL) (err error) {
func (swaggerLoader *SwaggerLoader) ResolveRefsIn(swagger *Swagger, location *url.URL) (err error) {
if swaggerLoader.visitedPathItemRefs == nil {
swaggerLoader.resetVisitedPathItemRefs()
}

// Visit all components
components := swagger.Components
for _, component := range components.Headers {
if err = swaggerLoader.resolveHeaderRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveHeaderRef(swagger, component, location); err != nil {
return
}
}
for _, component := range components.Parameters {
if err = swaggerLoader.resolveParameterRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveParameterRef(swagger, component, location); err != nil {
return
}
}
for _, component := range components.RequestBodies {
if err = swaggerLoader.resolveRequestBodyRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveRequestBodyRef(swagger, component, location); err != nil {
return
}
}
for _, component := range components.Responses {
if err = swaggerLoader.resolveResponseRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveResponseRef(swagger, component, location); err != nil {
return
}
}
for _, component := range components.Schemas {
if err = swaggerLoader.resolveSchemaRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveSchemaRef(swagger, component, location); err != nil {
return
}
}
for _, component := range components.SecuritySchemes {
if err = swaggerLoader.resolveSecuritySchemeRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveSecuritySchemeRef(swagger, component, location); err != nil {
return
}
}
for _, component := range components.Examples {
if err = swaggerLoader.resolveExampleRef(swagger, component, path); err != nil {
if err = swaggerLoader.resolveExampleRef(swagger, component, location); err != nil {
return
}
}
Expand All @@ -226,7 +227,7 @@ func (swaggerLoader *SwaggerLoader) ResolveRefsIn(swagger *Swagger, path *url.UR
if pathItem == nil {
continue
}
if err = swaggerLoader.resolvePathItemRef(swagger, entrypoint, pathItem, path); err != nil {
if err = swaggerLoader.resolvePathItemRef(swagger, entrypoint, pathItem, location); err != nil {
return
}
}
Expand Down
27 changes: 27 additions & 0 deletions openapi3/swagger_loader_issue220_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package openapi3

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func TestIssue220(t *testing.T) {
for _, specPath := range []string{
"testdata/my-openapi.json",
filepath.FromSlash("testdata/my-openapi.json"),
} {
t.Logf("specPath: %q", specPath)

loader := NewSwaggerLoader()
loader.IsExternalRefsAllowed = true
doc, err := loader.LoadSwaggerFromFile(specPath)
require.NoError(t, err)

err = doc.Validate(loader.Context)
require.NoError(t, err)

require.Equal(t, "integer", doc.Paths["/foo"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties["bar"].Value.Type)
}
}
18 changes: 18 additions & 0 deletions openapi3/testdata/my-openapi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"openapi": "3.0.2",
"info": {
"title": "My API",
"version": "0.1.0"
},
"paths": {
"/foo": {
"get": {
"responses": {
"200": {
"$ref": "my-other-openapi.json#/components/responses/DefaultResponse"
}
}
}
}
}
}
34 changes: 34 additions & 0 deletions openapi3/testdata/my-other-openapi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"openapi": "3.0.2",
"info": {
"title": "My other API",
"version": "0.1.0"
},
"components": {
"schemas": {
"DefaultObject": {
"type": "object",
"properties": {
"foo": {
"type": "string"
},
"bar": {
"type": "integer"
}
}
}
},
"responses": {
"DefaultResponse": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DefaultObject"
}
}
}
}
}
}
}

0 comments on commit a4e36cd

Please sign in to comment.