Repository: getkin/kin-openapi
Pull request #448 (2021-11-15 10:01:05)

try reproducing #447


Patch:
diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go
index e9f3164..2457026 100644
--- a/openapi2conv/openapi2_conv.go
+++ b/openapi2conv/openapi2_conv.go
@@ -525,6 +525,8 @@ func ToV3SecurityScheme(securityScheme *openapi2.SecurityScheme) (*openapi3.Secu
 			flows.AuthorizationCode = flow
 		case "password":
 			flows.Password = flow
+		case "application":
+			flows.ClientCredentials = flow
 		default:
 			return nil, fmt.Errorf("unsupported flow %q", securityScheme.Flow)
 		}
@@ -1076,6 +1078,8 @@ func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*o
 				result.Flow = "accessCode"
 			} else if flow = flows.Password; flow != nil {
 				result.Flow = "password"
+			} else if flow = flows.ClientCredentials; flow != nil {
+				result.Flow = "application"
 			} else {
 				return nil, nil
 			}
diff --git a/routers/gorillamux/router.go b/routers/gorillamux/router.go
index 31d8dc8..eec1f01 100644
--- a/routers/gorillamux/router.go
+++ b/routers/gorillamux/router.go
@@ -35,10 +35,16 @@ func NewRouter(doc *openapi3.T) (routers.Router, error) {
 	servers := make([]srv, 0, len(doc.Servers))
 	for _, server := range doc.Servers {
 		serverURL := server.URL
-		scheme0 := strings.Split(serverURL, "://")[0]
-		schemes := permutePart(scheme0, server)
-
-		u, err := url.Parse(bEncode(strings.Replace(serverURL, scheme0+"://", schemes[0]+"://", 1)))
+		var schemes []string
+		var u *url.URL
+		var err error
+		if strings.Contains(serverURL, "://") {
+			scheme0 := strings.Split(serverURL, "://")[0]
+			schemes = permutePart(scheme0, server)
+			u, err = url.Parse(bEncode(strings.Replace(serverURL, scheme0+"://", schemes[0]+"://", 1)))
+		} else {
+			u, err = url.Parse(bEncode(serverURL))
+		}
 		if err != nil {
 			return nil, err
 		}


Test patch:
diff --git a/openapi2conv/issue187_test.go b/openapi2conv/issue187_test.go
index 7ca85ca..1c113b7 100644
--- a/openapi2conv/issue187_test.go
+++ b/openapi2conv/issue187_test.go
@@ -167,3 +167,27 @@ paths:
 	err = doc3.Validate(context.Background())
 	require.NoError(t, err)
 }
+
+func TestPR449(t *testing.T) {
+	spec := `
+swagger: '2.0'
+info:
+  version: 1.0.0
+  title: title
+
+securityDefinitions:
+  OAuth2Application:
+    type: "oauth2"
+    flow: "application"
+    tokenUrl: "example.com/oauth2/token"
+`
+	doc3, err := v2v3YAML([]byte(spec))
+	require.NoError(t, err)
+	require.NotNil(t, doc3.Components.SecuritySchemes["OAuth2Application"].Value.Flows.ClientCredentials)
+	_, err = yaml.Marshal(doc3)
+	require.NoError(t, err)
+
+	doc2, err := FromV3(doc3)
+	require.NoError(t, err)
+	require.Equal(t, doc2.SecurityDefinitions["OAuth2Application"].Flow, "application")
+}
diff --git a/openapi3/loader_recursive_ref_test.go b/openapi3/loader_recursive_ref_test.go
index bd65903..5b7c150 100644
--- a/openapi3/loader_recursive_ref_test.go
+++ b/openapi3/loader_recursive_ref_test.go
@@ -11,7 +11,39 @@ func TestLoaderSupportsRecursiveReference(t *testing.T) {
 	loader.IsExternalRefsAllowed = true
 	doc, err := loader.LoadFromFile("testdata/recursiveRef/openapi.yml")
 	require.NoError(t, err)
-	require.NotNil(t, doc)
-	require.NoError(t, doc.Validate(loader.Context))
+	err = doc.Validate(loader.Context)
+	require.NoError(t, err)
 	require.Equal(t, "bar", doc.Paths["/foo"].Get.Responses.Get(200).Value.Content.Get("application/json").Schema.Value.Properties["foo2"].Value.Properties["foo"].Value.Properties["bar"].Value.Example)
 }
+
+func TestIssue447(t *testing.T) {
+	loader := NewLoader()
+	doc, err := loader.LoadFromData([]byte(`
+openapi: 3.0.1
+info:
+  title: Recursive refs example
+  version: "1.0"
+paths: {}
+components:
+  schemas:
+    Complex:
+      type: object
+      properties:
+        parent:
+          $ref: '#/components/schemas/Complex'
+`))
+	require.NoError(t, err)
+	err = doc.Validate(loader.Context)
+	require.NoError(t, err)
+	require.Equal(t, "object", doc.Components.
+		// Complex
+		Schemas["Complex"].
+		// parent
+		Value.Properties["parent"].
+		// parent
+		Value.Properties["parent"].
+		// parent
+		Value.Properties["parent"].
+		// type
+		Value.Type)
+}
diff --git a/routers/gorillamux/router_test.go b/routers/gorillamux/router_test.go
index 8dc0a2e..6c66018 100644
--- a/routers/gorillamux/router_test.go
+++ b/routers/gorillamux/router_test.go
@@ -219,3 +219,26 @@ func TestServerPath(t *testing.T) {
 	})
 	require.NoError(t, err)
 }
+
+func TestRelativeURL(t *testing.T) {
+	helloGET := &openapi3.Operation{Responses: openapi3.NewResponses()}
+	doc := &openapi3.T{
+		Servers: openapi3.Servers{
+			&openapi3.Server{
+				URL: "/api/v1",
+			},
+		},
+		Paths: openapi3.Paths{
+			"/hello": &openapi3.PathItem{
+				Get: helloGET,
+			},
+		},
+	}
+	router, err := NewRouter(doc)
+	require.NoError(t, err)
+	req, err := http.NewRequest(http.MethodGet, "https://example.com/api/v1/hello", nil)
+	require.NoError(t, err)
+	route, _, err := router.FindRoute(req)
+	require.NoError(t, err)
+	require.Equal(t, "/hello", route.Path)
+}