From 70d60f7ee7251f7866e1e87d4626143811b1e7d9 Mon Sep 17 00:00:00 2001 From: Thevakumar-Luheerathan Date: Thu, 25 Aug 2022 15:51:52 +0530 Subject: [PATCH] Handle escape sequences --- ballerina-tests/main.bal | 9 ++ .../tests/resources/escape-seq.json | 108 ++++++++++++++++++ ballerina-tests/tests/test.bal | 10 ++ .../azurefunctions/test/HandlerTest.java | 13 ++- .../src/test/resources/handlers/main.bal | 9 ++ .../AzureFunctionNameGenerator.java | 4 +- .../service/http/HTTPTriggerBinding.java | 4 +- 7 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 ballerina-tests/tests/resources/escape-seq.json diff --git a/ballerina-tests/main.bal b/ballerina-tests/main.bal index 6c30d107..d649c5cb 100644 --- a/ballerina-tests/main.bal +++ b/ballerina-tests/main.bal @@ -11,6 +11,15 @@ type Person record { int age; }; +listener af:HTTPListener ep1 = new (); + +service /hello\- on ep1 { + + resource function post hello\-query() returns string|error { + return "Hello from the hello-query"; + } +} + service /hello on ep { resource function default all() returns @af:HttpOutput string { return "Hello from all"; diff --git a/ballerina-tests/tests/resources/escape-seq.json b/ballerina-tests/tests/resources/escape-seq.json new file mode 100644 index 00000000..62b8c896 --- /dev/null +++ b/ballerina-tests/tests/resources/escape-seq.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/api/hello-/hello-query", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/api/hello-/hello-query" + ], + "X-WAWS-Unencoded-URL": [ + "/api/hello-/hello-query" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/api/hello-/hello-query", + "X-WAWS-Unencoded-URL": "/api/hello-/hello-query" + }, + "sys": { + "MethodName": "post-hello--hello-query", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/test.bal b/ballerina-tests/tests/test.bal index 1f223cef..6c39fa05 100644 --- a/ballerina-tests/tests/test.bal +++ b/ballerina-tests/tests/test.bal @@ -4,6 +4,16 @@ import ballerina/lang.value; import ballerina/regex; import ballerina/test; +@test:Config {} +function testEscapeSequences() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/escape-seq.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello--hello-query", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from the hello-query"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + @test:Config {} function testDefault() returns error? { final http:Client clientEndpoint = check new ("http://localhost:3000"); diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/HandlerTest.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/HandlerTest.java index b0a6c81d..3c824cd1 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/HandlerTest.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/HandlerTest.java @@ -73,7 +73,7 @@ public void compileSample() { DiagnosticResult diagnosticResult = compilation.diagnosticResult(); Assert.assertFalse(diagnosticResult.hasErrors()); - Assert.assertEquals(generatedFunctions.size(), 18); + Assert.assertEquals(generatedFunctions.size(), 19); } @Test @@ -186,4 +186,15 @@ public void testBlobTrigger() { JsonElement parse = jsonParser.parse(str); Assert.assertEquals(actual, parse); } + + @Test + public void testEscapeSequence() { + JsonObject httpHello = generatedFunctions.get("post-hello--hello-query"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello-/hello-query\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } } diff --git a/compiler-plugin-tests/src/test/resources/handlers/main.bal b/compiler-plugin-tests/src/test/resources/handlers/main.bal index 11ebb6df..46186040 100644 --- a/compiler-plugin-tests/src/test/resources/handlers/main.bal +++ b/compiler-plugin-tests/src/test/resources/handlers/main.bal @@ -11,6 +11,15 @@ type Person record { int age; }; +listener af:HTTPListener ep1 = new (); + +service /hello\- on ep1 { + + resource function post hello\-query() returns string|error { + return "Hello from the hello-query"; + } +} + // @af:HTTPTest service /hello on ep { resource function default all() returns @af:HttpOutput string { diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java index 4a99d396..5bde8d30 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java @@ -38,10 +38,12 @@ public AzureFunctionNameGenerator(ServiceDeclarationNode serviceDeclarationNode) private String getFunctionName(String servicePath, FunctionDefinitionNode functionDefinitionNode) { String method = functionDefinitionNode.functionName().text(); StringBuilder resourcePath = new StringBuilder(); + servicePath = servicePath.replace("\\", ""); resourcePath.append(servicePath); for (Node pathBlock : functionDefinitionNode.relativeResourcePath()) { if (pathBlock.kind() == SyntaxKind.IDENTIFIER_TOKEN) { - resourcePath.append("/").append(((IdentifierToken) pathBlock).text()); + String specialCharReplacedPathBlock = (((IdentifierToken) pathBlock).text()).replace("\\", ""); + resourcePath.append("/").append(specialCharReplacedPathBlock); } else if (pathBlock.kind() == SyntaxKind.RESOURCE_PATH_SEGMENT_PARAM) { Token token = ((ResourcePathParameterNode) pathBlock).paramName(); resourcePath.append("/").append(token.text()); diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java index 35aa8ba7..3c80bcb6 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java @@ -57,6 +57,7 @@ public List getBindings() { Optional httpTriggerAnnot = getListenerAnnotation(this.serviceDeclarationNode, Constants.ANNOTATION_HTTP_TRIGGER); String servicePath = Util.resourcePathToString(serviceDeclarationNode.absoluteResourcePath()); + servicePath = servicePath.replace("\\", ""); List functionContexts = new ArrayList<>(); NodeList members = this.serviceDeclarationNode.members(); for (Node node : members) { @@ -76,7 +77,8 @@ public List getBindings() { resourcePath.append(servicePath); for (Node pathBlock : functionDefinitionNode.relativeResourcePath()) { if (pathBlock.kind() == SyntaxKind.IDENTIFIER_TOKEN) { - resourcePath.append("/" + ((IdentifierToken) pathBlock).text()); + String specialCharReplacedPathBlock = (((IdentifierToken) pathBlock).text()).replace("\\", ""); + resourcePath.append("/").append(specialCharReplacedPathBlock); continue; } if (pathBlock.kind() == SyntaxKind.RESOURCE_PATH_SEGMENT_PARAM) {