diff --git a/adapter/internal/oasparser/model/api_env.go b/adapter/internal/oasparser/model/api_env.go index 453cdc0771..4fbae8bc08 100644 --- a/adapter/internal/oasparser/model/api_env.go +++ b/adapter/internal/oasparser/model/api_env.go @@ -35,7 +35,7 @@ func retrieveEndpointsFromEnv(apiHashValue string) ([]Endpoint, []Endpoint) { break } - productionEndpoint, err := getHostandBasepathandPort(productionEndpointURL) + productionEndpoint, err := getHTTPEndpoint(productionEndpointURL) if err != nil { loggers.LoggerAPI.Errorf("error while reading production endpoint : %v in env variables, %v", productionEndpointURL, err.Error()) } else if productionEndpoint != nil { @@ -52,7 +52,7 @@ func retrieveEndpointsFromEnv(apiHashValue string) ([]Endpoint, []Endpoint) { break } - sandboxEndpoint, err := getHostandBasepathandPort(sandboxEndpointURL) + sandboxEndpoint, err := getHTTPEndpoint(sandboxEndpointURL) if err != nil { loggers.LoggerAPI.Errorf("error while reading sandbox endpoint : %v in env variables, %v", sandboxEndpointURL, err.Error()) } else if sandboxEndpoint != nil { diff --git a/adapter/internal/oasparser/model/async_api.go b/adapter/internal/oasparser/model/async_api.go index 5b41063c8e..53437945ea 100644 --- a/adapter/internal/oasparser/model/async_api.go +++ b/adapter/internal/oasparser/model/async_api.go @@ -97,7 +97,7 @@ func (swagger *MgwSwagger) SetInfoAsyncAPI(asyncAPI AsyncAPI) error { swagger.apiType = WS if asyncAPI.Servers.Production.URL != "" { - endpoint, err := getEndpointForWebsocketURL(asyncAPI.Servers.Production.URL) + endpoint, err := getWebSocketEndpoint(asyncAPI.Servers.Production.URL) if err == nil { productionEndpoints := append([]Endpoint{}, *endpoint) swagger.productionEndpoints = generateEndpointCluster("clusterProd", diff --git a/adapter/internal/oasparser/model/constants.go b/adapter/internal/oasparser/model/constants.go index 0837f1e787..4b7871e652 100644 --- a/adapter/internal/oasparser/model/constants.go +++ b/adapter/internal/oasparser/model/constants.go @@ -80,6 +80,8 @@ const ( WS string = "WS" // WEBHOOK - API type for WEBHOOK APIs WEBHOOK string = "WEBHOOK" + // GRAPHQL - API type for GRAPHQL APIs + GRAPHQL string = "GRAPHQL" ) // Constants to represent errors diff --git a/adapter/internal/oasparser/model/mgw_swagger.go b/adapter/internal/oasparser/model/mgw_swagger.go index e2fd976323..eed447ed23 100644 --- a/adapter/internal/oasparser/model/mgw_swagger.go +++ b/adapter/internal/oasparser/model/mgw_swagger.go @@ -468,7 +468,7 @@ func (swagger *MgwSwagger) SetEnvLabelProperties(envProps synchronizer.APIEnvPro if envProps.APIConfigs.SandboxEndpointChoreo != "" && !conf.ControlPlane.DynamicEnvironments.Enabled { logger.LoggerOasparser.Infof("SandboxEndpointChoreo is found in env properties for %v : %v", swagger.title, swagger.version) - endpoint, err := getHostandBasepathandPort(envProps.APIConfigs.SandboxEndpointChoreo) + endpoint, err := getHTTPEndpoint(envProps.APIConfigs.SandboxEndpointChoreo) if err == nil { productionUrls = append(productionUrls, *endpoint) } else { @@ -487,7 +487,7 @@ func (swagger *MgwSwagger) SetEnvLabelProperties(envProps synchronizer.APIEnvPro if envProps.APIConfigs.ProductionEndpoint != "" { logger.LoggerOasparser.Infof("Production endpoints are found in env properties for %v : %v", swagger.title, swagger.version) - endpoint, err := getHostandBasepathandPort(envProps.APIConfigs.ProductionEndpoint) + endpoint, err := getHTTPEndpoint(envProps.APIConfigs.ProductionEndpoint) if err == nil { productionUrls = append(productionUrls, *endpoint) } else { @@ -503,7 +503,7 @@ func (swagger *MgwSwagger) SetEnvLabelProperties(envProps synchronizer.APIEnvPro if envProps.APIConfigs.SandBoxEndpoint != "" { logger.LoggerOasparser.Infof("Sandbox endpoints are found in env properties %v : %v", swagger.title, swagger.version) - endpoint, err := getHostandBasepathandPort(envProps.APIConfigs.SandBoxEndpoint) + endpoint, err := getHTTPEndpoint(envProps.APIConfigs.SandBoxEndpoint) if err == nil { sandboxUrls = append(sandboxUrls, *endpoint) } else { @@ -931,7 +931,7 @@ func processEndpointUrls(urlsArray []interface{}) ([]Endpoint, error) { logger.LoggerOasparser.Error("Consul syntax parse error ", err) continue } - endpoint, err := getHostandBasepathandPort(defHost) + endpoint, err := getHTTPEndpoint(defHost) if err == nil { endpoint.ServiceDiscoveryString = queryString endpoints = append(endpoints, *endpoint) @@ -939,7 +939,7 @@ func processEndpointUrls(urlsArray []interface{}) ([]Endpoint, error) { return nil, err } } else { - endpoint, err := getHostandBasepathandPort(v.(string)) + endpoint, err := getHTTPEndpoint(v.(string)) if err == nil { endpoints = append(endpoints, *endpoint) } else { @@ -1112,7 +1112,7 @@ func (swagger *MgwSwagger) GetInterceptor(vendorExtensions map[string]interface{ //serviceURL mandatory if v, found := val[serviceURL]; found { serviceURLV := v.(string) - endpoint, err := getHostandBasepathandPort(serviceURLV) + endpoint, err := getHTTPEndpoint(serviceURLV) if err != nil { logger.LoggerOasparser.Error("Error reading interceptors service url value", err) return InterceptEndpoint{}, errors.New("error reading interceptors service url value") @@ -1305,7 +1305,7 @@ func (swagger *MgwSwagger) PopulateSwaggerFromAPIYaml(apiData APIYaml, apiType s var unProcessedURLs []interface{} for _, endpointConfig := range endpointConfig.ProductionEndpoints { if apiType == WS { - prodEndpoint, err := getEndpointForWebsocketURL(endpointConfig.Endpoint) + prodEndpoint, err := getWebSocketEndpoint(endpointConfig.Endpoint) if err == nil { endpoints = append(endpoints, *prodEndpoint) } else { @@ -1319,7 +1319,7 @@ func (swagger *MgwSwagger) PopulateSwaggerFromAPIYaml(apiData APIYaml, apiType s endpointType = FailOver for _, endpointConfig := range endpointConfig.ProductionFailoverEndpoints { if apiType == WS { - failoverEndpoint, err := getEndpointForWebsocketURL(endpointConfig.Endpoint) + failoverEndpoint, err := getWebSocketEndpoint(endpointConfig.Endpoint) if err == nil { endpoints = append(endpoints, *failoverEndpoint) } else { @@ -1347,7 +1347,7 @@ func (swagger *MgwSwagger) PopulateSwaggerFromAPIYaml(apiData APIYaml, apiType s var unProcessedURLs []interface{} for _, endpointConfig := range endpointConfig.SandBoxEndpoints { if apiType == WS { - sandBoxEndpoint, err := getEndpointForWebsocketURL(endpointConfig.Endpoint) + sandBoxEndpoint, err := getWebSocketEndpoint(endpointConfig.Endpoint) if err == nil { endpoints = append(endpoints, *sandBoxEndpoint) } else { @@ -1361,7 +1361,7 @@ func (swagger *MgwSwagger) PopulateSwaggerFromAPIYaml(apiData APIYaml, apiType s endpointType = FailOver for _, endpointConfig := range endpointConfig.SandboxFailoverEndpoints { if apiType == WS { - failoverEndpoint, err := getEndpointForWebsocketURL(endpointConfig.Endpoint) + failoverEndpoint, err := getWebSocketEndpoint(endpointConfig.Endpoint) if err == nil { endpoints = append(endpoints, *failoverEndpoint) } else { diff --git a/adapter/internal/oasparser/model/open_api.go b/adapter/internal/oasparser/model/open_api.go index cbc9df1c98..6c561ff38e 100644 --- a/adapter/internal/oasparser/model/open_api.go +++ b/adapter/internal/oasparser/model/open_api.go @@ -88,7 +88,7 @@ func (swagger *MgwSwagger) SetInfoOpenAPI(swagger3 openapi3.Swagger) error { if len(serverEntry.URL) == 0 || strings.HasPrefix(serverEntry.URL, "/") { continue } - endpoint, err := getHostandBasepathandPort(serverEntry.URL) + endpoint, err := getHTTPEndpoint(serverEntry.URL) if err == nil { productionUrls = append(productionUrls, *endpoint) swagger.xWso2Basepath = endpoint.Basepath @@ -160,7 +160,7 @@ func setResourcesOpenAPI(openAPI openapi3.Swagger) ([]*Resource, error) { if len(serverEntry.URL) == 0 || strings.HasPrefix(serverEntry.URL, "/") { continue } - endpoint, err := getHostandBasepathandPort(serverEntry.URL) + endpoint, err := getHTTPEndpoint(serverEntry.URL) if err == nil { productionUrls = append(productionUrls, *endpoint) @@ -207,12 +207,20 @@ func getOperationLevelDetails(operation *openapi3.Operation, method string) *Ope } +func getHTTPEndpoint(rawURL string) (*Endpoint, error) { + return getHostandBasepathandPort(HTTP, rawURL) +} + +func getWebSocketEndpoint(rawURL string) (*Endpoint, error) { + return getHostandBasepathandPort(WS, rawURL) +} + // getHostandBasepathandPort retrieves host, basepath and port from the endpoint defintion // from of the production endpoints url entry, combination of schemes and host (in openapi v2) // or server property. // // if no scheme is mentioned before the hostname, urlType would be assigned as http -func getHostandBasepathandPort(rawURL string) (*Endpoint, error) { +func getHostandBasepathandPort(apiType string, rawURL string) (*Endpoint, error) { var ( basepath string host string @@ -220,8 +228,15 @@ func getHostandBasepathandPort(rawURL string) (*Endpoint, error) { urlType string ) + // Remove leading and trailing spaces of rawURL + rawURL = strings.TrimSpace(rawURL) + if !strings.Contains(rawURL, "://") { - rawURL = "http://" + rawURL + if apiType == HTTP || apiType == GRAPHQL || apiType == WEBHOOK { + rawURL = "http://" + rawURL + } else if apiType == WS { + rawURL = "ws://" + rawURL + } } parsedURL, err := url.Parse(rawURL) if err != nil { @@ -244,7 +259,7 @@ func getHostandBasepathandPort(rawURL string) (*Endpoint, error) { } port = uint32(u32) } else { - if strings.HasPrefix(rawURL, "https://") { + if strings.HasPrefix(rawURL, "https://") || strings.HasPrefix(rawURL, "wss://") { port = uint32(443) } else { port = uint32(80) @@ -254,8 +269,12 @@ func getHostandBasepathandPort(rawURL string) (*Endpoint, error) { urlType = "http" if strings.HasPrefix(rawURL, "https://") { urlType = "https" - } else if !strings.HasPrefix(rawURL, "http://") { - rawURL = "http://" + rawURL + } else if strings.HasPrefix(rawURL, "http://") { + urlType = "http" + } else if strings.HasPrefix(rawURL, "wss://") { + urlType = "wss" + } else if strings.HasPrefix(rawURL, "ws://") { + urlType = "ws" } return &Endpoint{Host: host, Basepath: basepath, Port: port, URLType: urlType, RawURL: rawURL}, nil @@ -329,53 +348,3 @@ func GetXWso2Label(vendorExtensions openapi3.ExtensionProps) []string { } return []string{"default"} } - -func getEndpointForWebsocketURL(rawURL string) (*Endpoint, error) { - var ( - basepath string - host string - port uint32 - urlType string - ) - if !strings.Contains(rawURL, "://") { - rawURL = "ws://" + rawURL - } - parsedURL, err := url.Parse(rawURL) - if err != nil { - logger.LoggerOasparser.Errorf("Failed to parse the malformed endpoint %v. Error message: %v", rawURL, err) - return nil, err - } - - // Hostname validation - if !regexp.MustCompile(hostNameValidator).MatchString(parsedURL.Hostname()) { - logger.LoggerOasparser.Error("Malformed endpoint detected (Invalid host name) : ", rawURL) - return nil, errors.New("malformed endpoint detected (Invalid host name) : " + rawURL) - } - - host = parsedURL.Hostname() - if parsedURL.Path == "" { - basepath = "/" - } else { - basepath = parsedURL.Path - } - if parsedURL.Port() != "" { - u32, err := strconv.ParseUint(parsedURL.Port(), 10, 32) - if err != nil { - logger.LoggerOasparser.Error("Error passing port value to mgwSwagger", err) - } - port = uint32(u32) - } else { - if strings.HasPrefix(rawURL, "wss://") { - port = uint32(443) - } else { - port = uint32(80) - } - } - urlType = "ws" - if strings.HasPrefix(rawURL, "wss://") { - urlType = "wss" - } else if !strings.HasPrefix(rawURL, "ws://") { - rawURL = "ws://" + rawURL - } - return &Endpoint{Host: host, Basepath: basepath, Port: port, URLType: urlType, RawURL: rawURL}, nil -} diff --git a/adapter/internal/oasparser/model/open_api_internal_test.go b/adapter/internal/oasparser/model/open_api_internal_test.go index 6aa55dcb4d..ee6cd423db 100644 --- a/adapter/internal/oasparser/model/open_api_internal_test.go +++ b/adapter/internal/oasparser/model/open_api_internal_test.go @@ -178,7 +178,7 @@ func TestGetHostandBasepathandPort(t *testing.T) { }, } for _, item := range dataItems { - resultResources, err := getHostandBasepathandPort(item.input) + resultResources, err := getHTTPEndpoint(item.input) assert.Equal(t, item.result, resultResources, item.message) if resultResources != nil { assert.Nil(t, err, "Error encountered when processing the endpoint") @@ -219,7 +219,7 @@ func TestMalformedUrl(t *testing.T) { } for index := range suspectedRawUrls { - response, _ := getHostandBasepathandPort(suspectedRawUrls[index]) + response, _ := getHTTPEndpoint(suspectedRawUrls[index]) assert.Nil(t, response) } diff --git a/adapter/internal/oasparser/model/swagger.go b/adapter/internal/oasparser/model/swagger.go index d5e522d70a..fd6546cb91 100644 --- a/adapter/internal/oasparser/model/swagger.go +++ b/adapter/internal/oasparser/model/swagger.go @@ -72,7 +72,7 @@ func (swagger *MgwSwagger) SetInfoSwagger(swagger2 spec.Swagger) error { swagger2.Info.Title, swagger2.Info.Version) } } - endpoint, err := getHostandBasepathandPort(urlScheme + swagger2.Host + swagger2.BasePath) + endpoint, err := getHTTPEndpoint(urlScheme + swagger2.Host + swagger2.BasePath) if err == nil { productionEndpoints := append([]Endpoint{}, *endpoint) swagger.productionEndpoints = generateEndpointCluster(prodClustersConfigNamePrefix, productionEndpoints, LoadBalance) diff --git a/adapter/internal/oasparser/operator/operator_test.go b/adapter/internal/oasparser/operator/operator_test.go index 268ebb3516..4834e35fb4 100644 --- a/adapter/internal/oasparser/operator/operator_test.go +++ b/adapter/internal/oasparser/operator/operator_test.go @@ -147,7 +147,7 @@ func TestMgwSwaggerWebSocketSand(t *testing.T) { testGetMgwSwaggerWebSocket(t, apiYamlFilePath) } -//Test execution for GetOpenAPIVersionAndJSONContent +// Test execution for GetOpenAPIVersionAndJSONContent func TestGetOpenAPIVersionAndJSONContent(t *testing.T) { apiYamlFilePath := config.GetMgwHome() + "/../adapter/test-resources/envoycodegen" @@ -164,7 +164,7 @@ func TestGetOpenAPIVersionAndJSONContent(t *testing.T) { } } -//helper function to test GetOpenAPIVersionAndJSONContent +// helper function to test GetOpenAPIVersionAndJSONContent func testGetOpenAPIVersionAndJSONContent(t *testing.T, apiYamlFilePath string) { apiYamlByteArr, err := ioutil.ReadFile(apiYamlFilePath) @@ -195,7 +195,7 @@ func testGetOpenAPIVersionAndJSONContent(t *testing.T, apiYamlFilePath string) { } -//Test execution for TestGetOpenAPIV3Struct +// Test execution for TestGetOpenAPIV3Struct func TestGetOpenAPIV3Struct(t *testing.T) { apiYamlFilePath := config.GetMgwHome() + "/../adapter/test-resources/envoycodegen" files, err := ioutil.ReadDir(apiYamlFilePath) @@ -211,7 +211,7 @@ func TestGetOpenAPIV3Struct(t *testing.T) { } } -//helper function for TestGetOpenAPIV3Struct +// helper function for TestGetOpenAPIV3Struct func testGetOpenAPIV3Struct(t *testing.T, apiYamlFilePath string) { apiYamlByteArr, err := ioutil.ReadFile(apiYamlFilePath) assert.Nil(t, err, "Error while reading the openapi.yaml file : %v"+apiYamlFilePath) @@ -245,14 +245,14 @@ func testGetMgwSwaggerWebSocket(t *testing.T, apiYamlFilePath string) { productionEndpoints := mgwSwagger.GetProdEndpoints().Endpoints productionEndpoint := productionEndpoints[0] assert.Equal(t, productionEndpoint.Host, "echo.websocket.org", "mgwSwagger production endpoint host mismatch") - assert.Equal(t, productionEndpoint.Basepath, "/", "mgwSwagger production endpoint basepath mistmatch") + assert.Equal(t, productionEndpoint.Basepath, "", "mgwSwagger production endpoint basepath mistmatch") assert.Equal(t, productionEndpoint.URLType, "ws", "mgwSwagger production endpoint URLType mismatch") var port uint32 = 80 assert.Equal(t, productionEndpoint.Port, port, "mgwSwagger production endpoint port mismatch") sandboxEndpoints := mgwSwagger.GetSandEndpoints().Endpoints sandboxEndpoint := sandboxEndpoints[0] assert.Equal(t, sandboxEndpoint.Host, "echo.websocket.org", "mgwSwagger sandbox endpoint host mismatch") - assert.Equal(t, sandboxEndpoint.Basepath, "/", "mgwSwagger sandbox endpoint basepath mistmatch") + assert.Equal(t, sandboxEndpoint.Basepath, "", "mgwSwagger sandbox endpoint basepath mistmatch") assert.Equal(t, sandboxEndpoint.URLType, "ws", "mgwSwagger sandbox endpoint URLType mismatch") assert.Equal(t, sandboxEndpoint.Port, port, "mgwSwagger sandbox endpoint port mismatch") } @@ -265,7 +265,7 @@ func testGetMgwSwaggerWebSocket(t *testing.T, apiYamlFilePath string) { productionEndpoint := productionEndpoints[0] var port uint32 = 80 assert.Equal(t, productionEndpoint.Host, "echo.websocket.org", "mgwSwagger production endpoint host mismatch") - assert.Equal(t, productionEndpoint.Basepath, "/", "mgwSwagger production endpoint basepath mistmatch") + assert.Equal(t, productionEndpoint.Basepath, "", "mgwSwagger production endpoint basepath mistmatch") assert.Equal(t, productionEndpoint.URLType, "ws", "mgwSwagger production endpoint URLType mismatch") assert.Equal(t, productionEndpoint.Port, port, "mgwSwagger production endpoint port mismatch") sandboxEndpoints := mgwSwagger.GetSandEndpoints() @@ -281,7 +281,7 @@ func testGetMgwSwaggerWebSocket(t *testing.T, apiYamlFilePath string) { sandboxEndpoints := mgwSwagger.GetSandEndpoints().Endpoints sandboxEndpoint := sandboxEndpoints[0] assert.Equal(t, sandboxEndpoint.Host, "echo.websocket.org", "mgwSwagger sandbox endpoint host mismatch") - assert.Equal(t, sandboxEndpoint.Basepath, "/", "mgwSwagger sandbox endpoint basepath mistmatch") + assert.Equal(t, sandboxEndpoint.Basepath, "", "mgwSwagger sandbox endpoint basepath mistmatch") assert.Equal(t, sandboxEndpoint.URLType, "ws", "mgwSwagger sandbox endpoint URLType mismatch") assert.Equal(t, sandboxEndpoint.Port, port, "mgwSwagger sandbox endpoint port mismatch") productionEndpoints := mgwSwagger.GetProdEndpoints()