From 909a667b04490856380fa0347735091f3133ac38 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 31 Oct 2023 15:30:31 +0530 Subject: [PATCH 01/22] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8c0ee76..98717ce 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -22,7 +22,7 @@ dependencies = [ [[package]] org = "ballerina" name = "cache" -version = "3.7.1" +version = "3.7.0" dependencies = [ {org = "ballerina", name = "constraint"}, {org = "ballerina", name = "jballerina.java"}, @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.3" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From 032b492d495f68c220a91a5161cf77de13fd2d87 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 31 Oct 2023 15:32:53 +0530 Subject: [PATCH 02/22] Fix returning mime:Entity[] responses --- ballerina/modules/soap11/soap11.bal | 10 +++++++--- ballerina/modules/soap12/soap12.bal | 10 +++++++--- ballerina/soap_utils.bal | 20 +++++++++++++------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 33ea2ee..03c1479 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -63,7 +63,7 @@ public isolated client class Client { xml envelope = body is xml ? body.clone() : mimeEntity.clone(); securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); } - xml response; + xml|mime:Entity[] response; if body is mime:Entity[] { body[0].setXml(securedBody); response = check soap:sendReceive(body, self.soapClient, action, headers, path, false); @@ -74,12 +74,16 @@ public isolated client class Client { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); do { if outboundSecurity is wssec:OutboundSecurityConfig { - return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + if response is xml { + return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + } else { + return check soap:applyOutboundConfig(outboundSecurity.clone(), check response[0].getXml().clone()); + } } } on fail var e { return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } - return response.clone(); + return response; } } on fail var e { return error Error(SOAP_ERROR, e.cause()); diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index fe8706a..011cd5b 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -63,7 +63,7 @@ public isolated client class Client { securedBody = body is xml ? check soap:applySecurityPolicies(self.inboundSecurity.clone(), body.clone()) : check soap:applySecurityPolicies(self.inboundSecurity.clone(), mimeEntity.clone()); } - xml response; + xml|mime:Entity[] response; if body is mime:Entity[] { body[0].setXml(securedBody); response = check soap:sendReceive(body, self.soapClient, action, headers, path); @@ -74,12 +74,16 @@ public isolated client class Client { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); do { if outboundSecurity is wssec:OutboundSecurityConfig { - return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + if response is xml { + return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + } else { + return check soap:applyOutboundConfig(outboundSecurity.clone(), check response[0].getXml().clone()); + } } } on fail var e { return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } - return response.clone(); + return response; } } on fail var e { return error Error(SOAP_ERROR, e.cause()); diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index ae2bc99..1c6f856 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -97,7 +97,7 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}, string path = "", boolean soap12 = true) - returns xml|Error { + returns xml|mime:Entity[]|Error { http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) : createSoap11HttpRequest(body, soapAction, headers); do { @@ -112,7 +112,7 @@ public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpCli } public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, string path = "", boolean soap12 = true) returns Error? { + map headers = {}, string path = "", boolean soap12 = true) returns Error? { http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) : createSoap11HttpRequest(body, soapAction, headers); http:Response|http:ClientError response = httpClient->post(path, req); @@ -139,7 +139,7 @@ isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAct } isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, - map headers = {}) returns http:Request { + map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -161,15 +161,21 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc return req; } -isolated function createSoap12Response(http:Response response) returns xml|error { - xml payload = check response.getXmlPayload(); +isolated function createSoap12Response(http:Response response) returns xml|mime:Entity[]|error { xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; + xml|http:ClientError payload = response.getXmlPayload(); + if payload !is xml { + return check response.getBodyParts(); + } return payload; } -isolated function createSoap11Response(http:Response response) returns xml|error { - xml payload = check response.getXmlPayload(); +isolated function createSoap11Response(http:Response response) returns xml|mime:Entity[]|error { xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; + xml|http:ClientError payload = response.getXmlPayload(); + if payload !is xml { + return check response.getBodyParts(); + } return payload; } From 8fc4bb17b44c1dadcb5d01c7a9c4d087724dabf2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 11:20:12 +0530 Subject: [PATCH 03/22] Fix identifying outbound configurations in SOAP responses --- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap12/soap12.bal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 03c1479..6339452 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -73,7 +73,7 @@ public isolated client class Client { lock { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); do { - if outboundSecurity is wssec:OutboundSecurityConfig { + if outboundSecurity is wssec:OutboundSecurityConfig && outboundSecurity != {} { if response is xml { return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); } else { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 011cd5b..9bafd0b 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -73,7 +73,7 @@ public isolated client class Client { lock { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); do { - if outboundSecurity is wssec:OutboundSecurityConfig { + if outboundSecurity is wssec:OutboundSecurityConfig && outboundSecurity != {} { if response is xml { return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); } else { From 4ac220bb0bc53db2c6f505f4cff8384a2723cd22 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 11:24:03 +0530 Subject: [PATCH 04/22] Fix sending SOAP 1.2 requests --- ballerina/modules/soap12/soap12.bal | 12 ++++-------- ballerina/soap_utils.bal | 10 +++------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 9bafd0b..4113cad 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -60,8 +60,8 @@ public isolated client class Client { xml securedBody; xml mimeEntity = body is xml ? body : check body[0].getXml(); lock { - securedBody = body is xml ? check soap:applySecurityPolicies(self.inboundSecurity.clone(), body.clone()) - : check soap:applySecurityPolicies(self.inboundSecurity.clone(), mimeEntity.clone()); + xml envelope = body is xml ? body.clone() : mimeEntity.clone(); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); } xml|mime:Entity[] response; if body is mime:Entity[] { @@ -107,12 +107,8 @@ public isolated client class Client { xml securedBody; xml mimeEntity = body is xml ? body : check body[0].getXml(); lock { - securedBody = body is xml ? check soap:applySecurityPolicies(self.inboundSecurity.clone(), body.clone()) - : check soap:applySecurityPolicies(self.inboundSecurity.clone(), mimeEntity.clone()); - } - if body is mime:Entity[] { - body[0].setXml(securedBody); - return check soap:sendOnly(body, self.soapClient, action, headers, path); + xml envelope = body is xml ? body.clone() : mimeEntity.clone(); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); } return check soap:sendOnly(securedBody, self.soapClient, action, headers, path); } on fail var e { diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 1c6f856..90c8737 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -143,17 +143,13 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc http:Request req = new; if body is xml { req.setXmlPayload(body); + req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); } else { req.setBodyParts(body); + req.setHeader(mime:CONTENT_TYPE, mime:MULTIPART_MIXED); } if soapAction is string { - var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); - if mediaType is mime:MediaType { - mediaType.parameters = {[ACTION]: soapAction}; - req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); - } - } else { - req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); + req.addHeader(SOAP_ACTION, soapAction); } foreach string key in headers.keys() { req.addHeader(key, headers[key].toBalString()); From 9e8562dfafbb3f0c15b3001d5237af85fc469249 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 11:25:32 +0530 Subject: [PATCH 05/22] Fix returning mime:Entity[] responses --- ballerina/soap_utils.bal | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 90c8737..01bc8db 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -159,18 +159,18 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc isolated function createSoap12Response(http:Response response) returns xml|mime:Entity[]|error { xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - xml|http:ClientError payload = response.getXmlPayload(); - if payload !is xml { - return check response.getBodyParts(); + mime:Entity[]|http:ClientError payload = response.getBodyParts(); + if payload !is mime:Entity[] { + return check response.getXmlPayload(); } return payload; } isolated function createSoap11Response(http:Response response) returns xml|mime:Entity[]|error { xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; - xml|http:ClientError payload = response.getXmlPayload(); - if payload !is xml { - return check response.getBodyParts(); + mime:Entity[]|http:ClientError payload = response.getBodyParts(); + if payload !is mime:Entity[] { + return check response.getXmlPayload(); } return payload; } From e805bf1d3b08f91998b43efece6b527e35cc629a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 11:41:30 +0530 Subject: [PATCH 06/22] Apply type inference to the SOAP responses --- ballerina/modules/soap11/soap11.bal | 17 ++++-- ballerina/modules/soap12/soap12.bal | 14 ++++- .../main/java/org/soap/ExecutionCallback.java | 41 +++++++++++++++ native/src/main/java/org/soap/Soap11.java | 52 +++++++++++++++++++ native/src/main/java/org/soap/Soap12.java | 51 ++++++++++++++++++ 5 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 native/src/main/java/org/soap/ExecutionCallback.java create mode 100644 native/src/main/java/org/soap/Soap11.java create mode 100644 native/src/main/java/org/soap/Soap12.java diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 6339452..82f15d8 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -19,6 +19,7 @@ import soap.wssec; import ballerina/http; import ballerina/mime; +import ballerina/jballerina.java; # Object for the basic SOAP client endpoint. public isolated client class Client { @@ -45,16 +46,26 @@ public isolated client class Client { # Sends SOAP request and expects a response. # ```ballerina - # xml|mime:Entity[] response = check soapClient->sendReceive(body, action); + # xml response = check soapClient->sendReceive(body, action); + # -- OR -- + # mime:Entity[] response = check soapClient->sendReceive(body, action); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + path - The resource path + # + typeParam - Default parameter use to infer the user specified type. # + return - If successful, returns the response. Else, returns an error - remote isolated function sendReceive(xml|mime:Entity[] body, string action, - map headers = {}, string path = "") + remote isolated function sendReceive(xml|mime:Entity[] body, string action, map headers = {}, + string path = "", typedesc typeParam = <>) + returns typeParam|Error = @java:Method { + 'class: "org.soap.Soap11" + } external; + + + isolated function generateResponse(xml|mime:Entity[] body, string action, + map headers = {}, string path = "") returns xml|mime:Entity[]|Error { do { xml securedBody; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 4113cad..ec7cf55 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -19,6 +19,7 @@ import soap.wssec; import ballerina/http; import ballerina/mime; +import ballerina/jballerina.java; # Object for the basic SOAP client endpoint. public isolated client class Client { @@ -45,15 +46,24 @@ public isolated client class Client { # Sends SOAP request and expects a response. # ```ballerina - # xml|mime:Entity[] response = check soapClient->sendReceive(body); + # xml response = check soapClient->sendReceive(body); + # -- OR -- + # mime:Entity[] response = check soapClient->sendReceive(body); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + path - The resource path + # + typeParam - Default parameter use to infer the user specified type. # + return - If successful, returns the response. Else, returns an error - remote isolated function sendReceive(xml|mime:Entity[] body, string? action = (), + remote isolated function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {}, + string path = "", typedesc typeParam = <>) + returns typeParam|Error = @java:Method { + 'class: "org.soap.Soap12" + } external; + + isolated function generateResponse(xml|mime:Entity[] body, string? action = (), map headers = {}, string path = "") returns xml|mime:Entity[]|Error { do { diff --git a/native/src/main/java/org/soap/ExecutionCallback.java b/native/src/main/java/org/soap/ExecutionCallback.java new file mode 100644 index 0000000..8005113 --- /dev/null +++ b/native/src/main/java/org/soap/ExecutionCallback.java @@ -0,0 +1,41 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.soap; + +import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.async.Callback; +import io.ballerina.runtime.api.values.BError; + +/** + * Callback class for executing Ballerina dependently type methods. + */ +public class ExecutionCallback implements Callback { + private final Future future; + + ExecutionCallback(Future future) { + this.future = future; + } + @Override + public void notifySuccess(Object o) { + this.future.complete(o); + } + + @Override + public void notifyFailure(BError bError) { + this.future.complete(bError); + } +} diff --git a/native/src/main/java/org/soap/Soap11.java b/native/src/main/java/org/soap/Soap11.java new file mode 100644 index 0000000..4f848b7 --- /dev/null +++ b/native/src/main/java/org/soap/Soap11.java @@ -0,0 +1,52 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.soap; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.async.StrandMetadata; +import io.ballerina.runtime.api.creators.TypeCreator; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BTypedesc; + +import static org.wssec.ModuleUtils.getModule; + + +public class Soap11 { + private static final String REMOTE_FUNCTION = "generateResponse"; + public static final StrandMetadata REMOTE_EXECUTION_STRAND = new StrandMetadata( + getModule().getOrg(), + getModule().getName(), + getModule().getMajorVersion(), + REMOTE_FUNCTION); + + public static Object sendReceive(Environment env, BObject soap11, Object body, BString action, + BMap headers, BString path, BTypedesc typeParam) { + Future future = env.markAsync(); + ExecutionCallback executionCallback = new ExecutionCallback(future); + UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_JSON_ARRAY, + PredefinedTypes.TYPE_ERROR); + Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; + env.getRuntime().invokeMethodAsyncConcurrently(soap11, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, + executionCallback, null, typeUnion, arguments); + return null; + } +} diff --git a/native/src/main/java/org/soap/Soap12.java b/native/src/main/java/org/soap/Soap12.java new file mode 100644 index 0000000..8c333fd --- /dev/null +++ b/native/src/main/java/org/soap/Soap12.java @@ -0,0 +1,51 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.soap; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.async.StrandMetadata; +import io.ballerina.runtime.api.creators.TypeCreator; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BTypedesc; + +import static org.wssec.ModuleUtils.getModule; + +public class Soap12 { + private static final String REMOTE_FUNCTION = "generateResponse"; + public static final StrandMetadata REMOTE_EXECUTION_STRAND = new StrandMetadata( + getModule().getOrg(), + getModule().getName(), + getModule().getMajorVersion(), + REMOTE_FUNCTION); + + public static Object sendReceive(Environment env, BObject soap12, Object body, Object action, + BMap headers, BString path, BTypedesc typeParam) { + Future future = env.markAsync(); + ExecutionCallback executionCallback = new ExecutionCallback(future); + UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_JSON_ARRAY, + PredefinedTypes.TYPE_ERROR); + Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; + env.getRuntime().invokeMethodAsyncConcurrently(soap12, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, + executionCallback, null, typeUnion, arguments); + return null; + } +} From c99139fed5e4668fae1bbf792aa98d05c2e5b8a9 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 11:43:24 +0530 Subject: [PATCH 07/22] Add test cases to validate type inference in responses --- .../soap11/tests/soap11_client_test.bal | 108 +++++++++++++++--- .../soap12/tests/soap12_client_test.bal | 92 ++++++++++++++- 2 files changed, 181 insertions(+), 19 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 37640a7..44f2d05 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -48,7 +48,7 @@ crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(ke crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); @test:Config { - groups: ["soap11", "send_receive", "mime", "aa"] + groups: ["soap11", "send_receive", "mime"] } function testSendReceiveWithMime() returns error? { Client soapClient = check new ("http://localhost:9090"); @@ -82,10 +82,88 @@ function testSendReceiveWithMime() returns error? { bytesPart.setContentId(""); mtomMessage.push(bytesPart); - xml|mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getPayload"); + xml response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getPayload"); test:assertEquals(response, body); } +@test:Config { + groups: ["soap11", "send_receive", "mime"] +} +function testSendReceiveWithMime2() returns error? { + Client soapClient = check new ("http://localhost:9090"); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + + xml response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getPayload"); + test:assertEquals(response, body); +} + +@test:Config { + groups: ["soap11", "send_receive", "mime"] +} +function testSendReceiveWithMime3() returns error? { + Client soapClient = check new ("http://localhost:9090"); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + + mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getMimePayload"); + test:assertEquals(response[0].getXml(), check mtomMessage[0].getXml()); +} + @test:Config { groups: ["soap11", "send_only"] } @@ -108,7 +186,7 @@ function testSendOnly() returns error? { @test:Config { groups: ["soap11", "send_receive"] } -function testSendReceive() returns error? { +function testsendReceive() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: NO_POLICY, @@ -126,7 +204,7 @@ function testSendReceive() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `5`; test:assertEquals(response, expected); } @@ -148,7 +226,7 @@ function testSendReceiveWithHeaders() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); @@ -193,13 +271,13 @@ function testSendReceiveError() returns error? { `; - xml|mime:Entity[]|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); test:assertTrue(response is Error); test:assertEquals((response).message(), SOAP_ERROR); } @test:Config { - groups: ["soap11", "send_receive", "kl"] + groups: ["soap11", "send_receive"] } function testSendReceiveWithTimestampTokenSecurity() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", @@ -221,7 +299,7 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -254,7 +332,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -301,7 +379,7 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -346,7 +424,7 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -371,7 +449,7 @@ function testSoapEndpoint() returns error? { } ); xml body = xml `23`; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); return soap:assertUsernameToken(response.toString(), username, password, wssec:TEXT, string `23`); } @@ -396,12 +474,12 @@ function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? { } ); xml body = xml `23`; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); return soap:assertSymmetricBinding(response.toString(), string `23`); } @test:Config { - groups: ["soap11", "send_receive", "j"] + groups: ["soap11", "send_receive"] } function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? { Client soapClient = check new ("http://localhost:9090", @@ -421,6 +499,6 @@ function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? } ); xml body = xml `23`; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); return soap:assertSymmetricBinding(response.toString(), string `23`); } diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 500e006..d4a6be3 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -18,11 +18,14 @@ import soap; import soap.wssec; import ballerina/crypto; +import ballerina/io; import ballerina/mime; import ballerina/test; const KEY_ALIAS = "wss40"; const KEY_PASSWORD = "security"; +const IMAGE_PATH = "../ballerina/icon.png"; +const FILE_PATH = "../ballerina/Module.md"; const KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; const X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; const X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; @@ -79,12 +82,90 @@ function testSendReceive12() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `5`; test:assertEquals(response, expected); } +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceive12Mime() returns error? { + Client soapClient = check new ("http://localhost:9090"); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + + mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getMimePayload"); + test:assertEquals(response[0].getXml(), check mtomMessage[0].getXml()); +} + +@test:Config { + groups: ["soap11", "send_receive", "mime"] +} +function testSendReceive12WithMime2() returns error? { + Client soapClient = check new ("http://localhost:9090"); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + + xml response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getPayload"); + test:assertEquals(response, body); +} + @test:Config { groups: ["soap12", "send_receive"] } @@ -103,7 +184,7 @@ function testSendReceive12WithHeaders() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", - {foo: ["bar1", "bar2"]}); + {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); @@ -375,6 +456,9 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { test:assertEquals(response.toString(), expected.toString()); } +@test:Config { + groups: ["soap12", "send_receive"] +} function testSoapEndpoint() returns error? { string username = "user"; string password = "password"; @@ -393,7 +477,7 @@ function testSoapEndpoint() returns error? { } @test:Config { - groups: ["soap11", "send_receive"] + groups: ["soap12", "send_receive"] } function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? { Client soapClient = check new ("http://localhost:9090", @@ -418,7 +502,7 @@ function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? { } @test:Config { - groups: ["soap11", "send_receive", "j"] + groups: ["soap12", "send_receive"] } function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? { Client soapClient = check new ("http://localhost:9090", From a9fdd66ec2ff848dd158c8128cf6241056507c49 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 11:44:14 +0530 Subject: [PATCH 08/22] Add resource functions to send mime:Entity[] payloads in mock services --- .../soap11/tests/http_soap_service.bal | 34 +++++++++++++------ .../soap12/tests/http_soap_service.bal | 34 +++++++++++++------ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index 75c69d5..bf464b7 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -16,6 +16,7 @@ import ballerina/crypto; import ballerina/http; +import ballerina/mime; import ballerina/soap; const crypto:KeyStore serverKeyStore = { @@ -34,6 +35,19 @@ service / on new http:Listener(9090) { return response; } + resource function post getMimePayload(http:Request request) returns http:Response|error { + http:Response response = new; + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(check (check request.getBodyParts())[0].getXml()); + mtomMessage.push(envelope); + response.setBodyParts(mtomMessage); + response.setPayload(mtomMessage); + return response; + } + resource function post getSamePayload(http:Request request) returns http:Response|error { xml payload = check request.getXmlPayload(); http:Response response = new; @@ -45,18 +59,18 @@ service / on new http:Listener(9090) { xml payload = check request.getXmlPayload(); xml applyOutboundConfig = check soap:applyOutboundConfig( { - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload); + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); xml securedEnv = check soap:applySecurityPolicies( { - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig); + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); http:Response response = new; response.setPayload(securedEnv); return response; diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index 5acebab..b873b00 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -16,6 +16,7 @@ import ballerina/crypto; import ballerina/http; +import ballerina/mime; import ballerina/soap; const crypto:KeyStore serverKeyStore = { @@ -34,6 +35,19 @@ service / on new http:Listener(9090) { return response; } + resource function post getMimePayload(http:Request request) returns http:Response|error { + http:Response response = new; + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(check (check request.getBodyParts())[0].getXml()); + mtomMessage.push(envelope); + response.setBodyParts(mtomMessage); + response.setPayload(mtomMessage); + return response; + } + resource function post getSamePayload(http:Request request) returns http:Response|error { xml payload = check request.getXmlPayload(); http:Response response = new; @@ -45,18 +59,18 @@ service / on new http:Listener(9090) { xml payload = check request.getXmlPayload(); xml applyOutboundConfig = check soap:applyOutboundConfig( { - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload); + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); xml securedEnv = check soap:applySecurityPolicies( { - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig); + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); http:Response response = new; response.setPayload(securedEnv); return response; From e547786917a0f25d95c610d454df9e86eba3360a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 14:19:37 +0530 Subject: [PATCH 09/22] Fix test cases to get single type responses --- .../soap12/tests/soap12_client_test.bal | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index d4a6be3..f2262a4 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -94,8 +94,8 @@ function testSendReceive12() returns error? { function testSendReceive12Mime() returns error? { Client soapClient = check new ("http://localhost:9090"); xml body = xml ` + xmlns:soap="http://www.w3.org/2003/05/soap-envelope" + soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> 2 @@ -133,8 +133,8 @@ function testSendReceive12Mime() returns error? { function testSendReceive12WithMime2() returns error? { Client soapClient = check new ("http://localhost:9090"); xml body = xml ` + xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" + soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding/"> 2 @@ -183,7 +183,7 @@ function testSendReceive12WithHeaders() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); xml expected = xml `5`; @@ -207,7 +207,7 @@ function testSendReceive12WithoutSoapAction() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml|mime:Entity[] response = check soapClient->sendReceive(body); + xml response = check soapClient->sendReceive(body); xml expected = xml `5`; test:assertEquals(response, expected); @@ -250,7 +250,7 @@ function testSendReceive12IncludingHeadersWithoutSoapAction() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml|mime:Entity[] response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]}); + xml response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); } @@ -292,7 +292,7 @@ function testSendReceiveError() returns error? { `; - xml|mime:Entity[]|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); test:assertTrue(response is Error); test:assertEquals((response).message(), SOAP_ERROR); } @@ -320,7 +320,7 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -354,7 +354,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -401,7 +401,7 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -447,7 +447,7 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() @@ -471,8 +471,8 @@ function testSoapEndpoint() returns error? { } } ); - xml body = xml `23`; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + xml body = xml `23`; + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); return soap:assertUsernameToken(response.toString(), username, password, wssec:TEXT, string `23`); } From 9a88fbf30070ccaf6c5b3e7ae64f5540620d879b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 14:21:23 +0530 Subject: [PATCH 10/22] Add test cases to validate outbound security configs in mime:Entity[] responses --- .../soap11/tests/http_soap_service.bal | 28 +++++ .../soap11/tests/soap11_client_test.bal | 108 ++++++++++++++++++ .../soap12/tests/http_soap_service.bal | 16 +-- 3 files changed, 144 insertions(+), 8 deletions(-) diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index bf464b7..0c356c5 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -55,6 +55,34 @@ service / on new http:Listener(9090) { return response; } + resource function post getSecuredMimePayload(http:Request request) returns http:Response|error { + xml payload = check (check request.getBodyParts())[0].getXml(); + xml applyOutboundConfig = check soap:applyOutboundConfig( + { + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); + xml securedEnv = check soap:applySecurityPolicies( + { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); + http:Response response = new; + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(securedEnv); + mtomMessage.push(envelope); + response.setBodyParts(mtomMessage); + response.setPayload(mtomMessage); + return response; + } + resource function post getSecuredPayload(http:Request request) returns http:Response|error { xml payload = check request.getXmlPayload(); xml applyOutboundConfig = check soap:applyOutboundConfig( diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 44f2d05..06fdfe5 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -502,3 +502,111 @@ function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); return soap:assertSymmetricBinding(response.toString(), string `23`); } + +@test:Config { + groups: ["soap11", "send_receive", "mime"] +} +function testOutboundConfigWithMime2() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: clientPrivateKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + xml response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getSecuredMimePayload"); + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; + test:assertEquals(response/, body/); +} + +@test:Config { + groups: ["soap11", "send_receive", "mime"] +} +function testInvalidOutboundConfigWithMime2() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + xml|Error response = soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getSecuredMimePayload"); + test:assertTrue(response is Error); + test:assertEquals((response).message(), "Outbound security configurations do not match with the SOAP response."); +} diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index b873b00..f7de73a 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -59,17 +59,17 @@ service / on new http:Listener(9090) { xml payload = check request.getXmlPayload(); xml applyOutboundConfig = check soap:applyOutboundConfig( { - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey }, payload); xml securedEnv = check soap:applySecurityPolicies( { - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey }, applyOutboundConfig); http:Response response = new; response.setPayload(securedEnv); From 246e8e5c0b25aac2755ffa4d52ae013f6979ce3c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 14:22:19 +0530 Subject: [PATCH 11/22] Fix indenting according to coding conventions --- native/src/main/java/org/soap/Soap11.java | 2 +- native/src/main/java/org/soap/Soap12.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native/src/main/java/org/soap/Soap11.java b/native/src/main/java/org/soap/Soap11.java index 4f848b7..90d7375 100644 --- a/native/src/main/java/org/soap/Soap11.java +++ b/native/src/main/java/org/soap/Soap11.java @@ -46,7 +46,7 @@ public static Object sendReceive(Environment env, BObject soap11, Object body, B PredefinedTypes.TYPE_ERROR); Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; env.getRuntime().invokeMethodAsyncConcurrently(soap11, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, - executionCallback, null, typeUnion, arguments); + executionCallback, null, typeUnion, arguments); return null; } } diff --git a/native/src/main/java/org/soap/Soap12.java b/native/src/main/java/org/soap/Soap12.java index 8c333fd..75cacf7 100644 --- a/native/src/main/java/org/soap/Soap12.java +++ b/native/src/main/java/org/soap/Soap12.java @@ -42,10 +42,10 @@ public static Object sendReceive(Environment env, BObject soap12, Object body, O Future future = env.markAsync(); ExecutionCallback executionCallback = new ExecutionCallback(future); UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_JSON_ARRAY, - PredefinedTypes.TYPE_ERROR); + PredefinedTypes.TYPE_ERROR); Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; env.getRuntime().invokeMethodAsyncConcurrently(soap12, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, - executionCallback, null, typeUnion, arguments); + executionCallback, null, typeUnion, arguments); return null; } } From 46fdf61d21b53e5e5f8dbaf8cc73e472a252d5ee Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 15:17:27 +0530 Subject: [PATCH 12/22] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 6 +++--- ballerina/Dependencies.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 447ce58..98830b0 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.8.0" +version = "0.8.1" authors = ["Ballerina"] export=["soap", "soap.soap11", "soap.soap12"] keywords = ["soap"] @@ -19,8 +19,8 @@ graalvmCompatible = true [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "soap-native" -version = "0.8.0" -path = "../native/build/libs/soap-native-0.8.0.jar" +version = "0.8.1" +path = "../native/build/libs/soap-native-0.8.1-SNAPSHOT.jar" [[platform.java17.dependency]] groupId = "org.apache.wss4j" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 98717ce..74ff3d8 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -269,7 +269,7 @@ dependencies = [ [[package]] org = "ballerina" name = "soap" -version = "0.8.0" +version = "0.8.1" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, From 7a5e640bbd585576958c5e2c98e367eff091248d Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 15:32:36 +0530 Subject: [PATCH 13/22] Apply changes to fix code coverage --- ballerina/modules/soap11/soap11.bal | 4 +- .../soap11/tests/soap11_client_test.bal | 22 +++++- ballerina/modules/soap12/soap12.bal | 3 +- .../soap12/tests/http_soap_service.bal | 28 +++++++ .../soap12/tests/soap12_client_test.bal | 75 +++++++++++++++++++ 5 files changed, 128 insertions(+), 4 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 82f15d8..74e8c57 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -63,7 +63,6 @@ public isolated client class Client { 'class: "org.soap.Soap11" } external; - isolated function generateResponse(xml|mime:Entity[] body, string action, map headers = {}, string path = "") returns xml|mime:Entity[]|Error { @@ -88,7 +87,8 @@ public isolated client class Client { if response is xml { return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); } else { - return check soap:applyOutboundConfig(outboundSecurity.clone(), check response[0].getXml().clone()); + return check soap:applyOutboundConfig(outboundSecurity.clone(), + check response[0].getXml().clone()); } } } on fail var e { diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 06fdfe5..0f27b04 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -183,6 +183,26 @@ function testSendOnly() returns error? { check soapClient->sendOnly(body, "http://tempuri.org/Add"); } +@test:Config { + groups: ["soap11", "send_only"] +} +function testSendOnlyError() returns error? { + xml body = xml ` + + + 2 + 3 + + + `; + + Client soapClient = check new ("error-url"); + Error? response = soapClient->sendOnly(body, "http://tempuri.org/Add", path = "/error"); + test:assertTrue(response is Error); +} + @test:Config { groups: ["soap11", "send_receive"] } @@ -560,7 +580,7 @@ function testOutboundConfigWithMime2() returns error? { @test:Config { groups: ["soap11", "send_receive", "mime"] } -function testInvalidOutboundConfigWithMime2() returns error? { +function testInvalidOutboundConfigWithMime() returns error? { Client soapClient = check new ("http://localhost:9090", { inboundSecurity: { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index ec7cf55..9d27c55 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -87,7 +87,8 @@ public isolated client class Client { if response is xml { return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); } else { - return check soap:applyOutboundConfig(outboundSecurity.clone(), check response[0].getXml().clone()); + return check soap:applyOutboundConfig(outboundSecurity.clone(), + check response[0].getXml().clone()); } } } on fail var e { diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index f7de73a..0191aaf 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -75,4 +75,32 @@ service / on new http:Listener(9090) { response.setPayload(securedEnv); return response; } + + resource function post getSecuredMimePayload(http:Request request) returns http:Response|error { + xml payload = check (check request.getBodyParts())[0].getXml(); + xml applyOutboundConfig = check soap:applyOutboundConfig( + { + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); + xml securedEnv = check soap:applySecurityPolicies( + { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); + http:Response response = new; + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(securedEnv); + mtomMessage.push(envelope); + response.setBodyParts(mtomMessage); + response.setPayload(mtomMessage); + return response; + } } diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index f2262a4..69c11ca 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -67,6 +67,26 @@ function testSendOnly12() returns error? { check soapClient->sendOnly(body, "http://tempuri.org/Add"); } +@test:Config { + groups: ["soap12", "send_only"] +} +function testSendOnlyError12() returns error? { + xml body = xml ` + + + 2 + 3 + + + `; + + Client soapClient = check new ("error-url"); + Error? response = soapClient->sendOnly(body, "http://tempuri.org/Add", path = "/error"); + test:assertTrue(response is Error); +} + @test:Config { groups: ["soap12", "send_receive"] } @@ -526,3 +546,58 @@ function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); return soap:assertSymmetricBinding(response.toString(), string `23`); } + +@test:Config { + groups: ["soap12", "send_receive"] +} +function testInvalidOutboundConfigWithMime12() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + + mime:Entity[]|Error response = soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getSecuredMimePayload"); + test:assertTrue(response is Error); + test:assertEquals((response).message(), "Outbound security configurations do not match with the SOAP response."); +} From 8b7bb39a37b9a0e08a69beaf4ddc19feddcb514a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 1 Nov 2023 21:32:00 +0530 Subject: [PATCH 14/22] Fix applying encryption in SOAP 1.2 envelopes --- ballerina/modules/soap11/soap11.bal | 8 +-- .../soap11/tests/http_soap_service.bal | 8 +-- .../soap12/tests/soap12_client_test.bal | 4 +- .../modules/wssec/tests/ws_security_tests.bal | 36 +++++++------- .../modules/wssec/ws_security_methods.bal | 49 +++++++++++++++---- ballerina/soap_utils.bal | 46 ++++++++++------- 6 files changed, 94 insertions(+), 57 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 74e8c57..5738b71 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -71,7 +71,7 @@ public isolated client class Client { xml mimeEntity = body is xml ? body : check body[0].getXml(); lock { xml envelope = body is xml ? body.clone() : mimeEntity.clone(); - securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone(), false); } xml|mime:Entity[] response; if body is mime:Entity[] { @@ -85,10 +85,10 @@ public isolated client class Client { do { if outboundSecurity is wssec:OutboundSecurityConfig && outboundSecurity != {} { if response is xml { - return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone(), false); } else { return check soap:applyOutboundConfig(outboundSecurity.clone(), - check response[0].getXml().clone()); + check response[0].getXml().clone(), false); } } } on fail var e { @@ -119,7 +119,7 @@ public isolated client class Client { xml mimeEntity = body is xml ? body : check body[0].getXml(); lock { xml envelope = body is xml ? body.clone() : mimeEntity.clone(); - securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone(), false); } return check soap:sendOnly(securedBody, self.soapClient, action, headers, path, false); } on fail var e { diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index 0c356c5..72eb50e 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -63,14 +63,14 @@ service / on new http:Listener(9090) { signatureAlgorithm: soap:RSA_SHA256, decryptionAlgorithm: soap:RSA_ECB, decryptionKey: serverPrivateKey - }, payload); + }, payload, false); xml securedEnv = check soap:applySecurityPolicies( { signatureAlgorithm: soap:RSA_SHA256, encryptionAlgorithm: soap:RSA_ECB, signatureKey: serverPrivateKey, encryptionKey: clientPublicKey - }, applyOutboundConfig); + }, applyOutboundConfig, false); http:Response response = new; mime:Entity[] mtomMessage = []; mime:Entity envelope = new; @@ -91,14 +91,14 @@ service / on new http:Listener(9090) { signatureAlgorithm: soap:RSA_SHA256, decryptionAlgorithm: soap:RSA_ECB, decryptionKey: serverPrivateKey - }, payload); + }, payload, false); xml securedEnv = check soap:applySecurityPolicies( { signatureAlgorithm: soap:RSA_SHA256, encryptionAlgorithm: soap:RSA_ECB, signatureKey: serverPrivateKey, encryptionKey: clientPublicKey - }, applyOutboundConfig); + }, applyOutboundConfig, false); http:Response response = new; response.setPayload(securedEnv); return response; diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 69c11ca..331848f 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -516,7 +516,7 @@ function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? { } } ); - xml body = xml `23`; + xml body = xml `23`; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); return soap:assertSymmetricBinding(response.toString(), string `23`); } @@ -542,7 +542,7 @@ function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? } ); - xml body = xml `23`; + xml body = xml `23`; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); return soap:assertSymmetricBinding(response.toString(), string `23`); } diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index ffd3145..29addfa 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -211,7 +211,7 @@ function testSymmetricBindingPolicyWithSignatureOnly() returns error? { servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -239,7 +239,7 @@ function testSymmetricBindingPolicyEncryptionOnly() returns error? { servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] encData = check getEncryptedData(securedEnvelope); @@ -266,7 +266,7 @@ function testSymmetricBindingWithSignatureAndEncryption() returns error? { symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -302,7 +302,7 @@ function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns erro x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -344,7 +344,7 @@ function testUsernameTokenWithSymmetricBinding() returns error? { symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -403,7 +403,7 @@ function testUsernameTokenTimestampWithSymmetricBindingAndX509Token() returns er x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -452,7 +452,7 @@ function testSymmetricBindingWithOutboundConfig() returns error? { servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, false, symmetricBinding); string envelopeString = securedEnvelope.toString(); OutboundSecurityConfig outboundConfig = { @@ -492,7 +492,7 @@ function testAsymmetricBindingWithSignatureRsaSha256() returns error? { signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, @@ -518,7 +518,7 @@ function testAsymmetricBindingWithX509Signature() returns error? { encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -544,7 +544,7 @@ function testAsymmetricBindingWithEncryption() returns error? { signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] encData = check getEncryptedData(securedEnvelope); @@ -571,7 +571,7 @@ function testAsymmetricBindingWithSignatureAndEncryption() returns error? { encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -604,7 +604,7 @@ function testAsymmetricBindingWithX509SignatureAndEncryption() returns error? { encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -644,7 +644,7 @@ function testUsernameTokenWithAsymmetricBindingAndX509() returns error? { encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -686,7 +686,7 @@ function testUsernameTokenTimestampWithAsymmetricBindingAndX509() returns error? encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -729,7 +729,7 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { decryptionKey: serverPrivateKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope,false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; if privateKey is crypto:PrivateKey|crypto:PublicKey { @@ -760,7 +760,7 @@ function testAsymmetricBindingWithSignatureWithRsaSha1() returns error? { signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, @@ -785,7 +785,7 @@ function testAsymmetricBindingWithSignatureWithRsaSha384() returns error? { signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, @@ -810,7 +810,7 @@ function testAsymmetricBindingWithSignatureWithRsaSha512() returns error? { signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, false, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 9e328d0..9fb5ae7 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -17,7 +17,8 @@ import ballerina/crypto; import ballerina/lang.regexp; -xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; +xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; +xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; xmlns "http://www.w3.org/2000/09/xmldsig#" as ds; isolated function addSecurityHeader(Document document) returns WSSecurityHeader|Error { @@ -129,9 +130,10 @@ public isolated function applyUsernameToken(xml envelope, *UsernameTokenConfig u # Apply symmetric binding security policy with username token to the SOAP envelope. # # + envelope - The SOAP envelope +# + soap12 - A boolean flag. Set to `true` for SOAP 1.2, or `false` for SOAP 1.1. # + symmetricBinding - The `SymmetricBindingConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symmetricBinding) +public isolated function applySymmetricBinding(xml envelope, boolean soap12, *SymmetricBindingConfig symmetricBinding) returns xml|crypto:Error|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); @@ -140,8 +142,15 @@ public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingCo EncryptionAlgorithm? encryptionAlgorithm = symmetricBinding.encryptionAlgorithm; if signatureAlgorithm is SignatureAlgorithm { Signature signature = check new (); - byte[] signedData = check signature.signData((envelope//*).toString(), signatureAlgorithm - , symmetricBinding.symmetricKey); + byte[] signedData; + if soap12 { + signedData = check signature.signData((envelope//*).toString(), signatureAlgorithm, + symmetricBinding.symmetricKey); + } else { + signedData = check signature.signData((envelope//*).toString(), signatureAlgorithm, + symmetricBinding.symmetricKey); + } + Signature signatureResult = check addSignature(signature, signatureAlgorithm, signedData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, @@ -149,8 +158,14 @@ public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingCo } if encryptionAlgorithm is EncryptionAlgorithm { Encryption encryption = check new (); - byte[] encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), - symmetricBinding.symmetricKey); + byte[] encryptData; + if soap12 { + encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), + symmetricBinding.symmetricKey); + } else { + encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), + symmetricBinding.symmetricKey); + } Encryption encryptionResult = check addEncryption(encryption, encryptionAlgorithm, encryptData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); @@ -163,9 +178,12 @@ public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingCo # Apply asymmetric binding security policy with X509 token to the SOAP envelope. # # + envelope - The SOAP envelope +# + soap12 - A boolean flag. Set to `true` for SOAP 1.2, or `false` for SOAP 1.1. # + asymmetricBinding - The `AsymmetricBindingConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig asymmetricBinding) returns xml|crypto:Error|Error { +public isolated function applyAsymmetricBinding(xml envelope, boolean soap12, + *AsymmetricBindingConfig asymmetricBinding) + returns xml|crypto:Error|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); @@ -177,8 +195,14 @@ public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBinding if signatureKey !is crypto:PrivateKey { return error Error("Signature key cannot be nil"); } - byte[] signedData = check signature.signData((envelope//*).toString(), - signatureAlgorithm, signatureKey); + byte[] signedData; + if soap12 { + signedData = check signature.signData((envelope//*).toString(), + signatureAlgorithm, signatureKey); + } else { + signedData = check signature.signData((envelope//*).toString(), + signatureAlgorithm, signatureKey); + } Signature signatureResult = check addSignature(signature, signatureAlgorithm, signedData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, @@ -190,7 +214,12 @@ public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBinding if encryptionKey !is crypto:PublicKey { return error Error("Encryption key cannot be nil"); } - byte[] encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), encryptionKey); + byte[] encryptData; + if soap12 { + encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), encryptionKey); + } else { + encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), encryptionKey); + } Encryption encryptionResult = check addEncryption(encryption, encryptionAlgorithm, encryptData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 01bc8db..6338234 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -18,9 +18,9 @@ import soap.wssec; import ballerina/crypto; import ballerina/http; -import ballerina/mime; -import ballerina/lang.regexp; import ballerina/jballerina.java; +import ballerina/lang.regexp; +import ballerina/mime; import ballerina/test; public isolated function validateTransportBindingPolicy(ClientConfig config) returns Error? { @@ -39,19 +39,20 @@ public isolated function validateTransportBindingPolicy(ClientConfig config) ret } public isolated function getReadOnlyClientConfig(ClientConfig original) returns readonly & ClientConfig = @java:Method { - 'class: "org.wssec.WsSecurity" + 'class: "org.wssec.WsSecurity" } external; public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] security, - xml envelope) returns xml|crypto:Error|wssec:Error { + xml envelope, boolean soap12 = true) + returns xml|crypto:Error|wssec:Error { if security is wssec:TimestampTokenConfig { return wssec:applyTimestampToken(envelope, security); } else if security is wssec:UsernameTokenConfig { return wssec:applyUsernameToken(envelope, security); } else if security is wssec:SymmetricBindingConfig { - return wssec:applySymmetricBinding(envelope, security); + return wssec:applySymmetricBinding(envelope, soap12, security); } else if security is wssec:AsymmetricBindingConfig { - return wssec:applyAsymmetricBinding(envelope, security); + return wssec:applyAsymmetricBinding(envelope, soap12, security); } else if security is wssec:InboundSecurityConfig { return envelope; } else { @@ -63,9 +64,10 @@ public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec } } -public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) - returns xml|Error { - xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; +public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope, + boolean soap12 = true) returns xml|Error { + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; + xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; xml soapEnvelope = envelope; do { wssec:EncryptionAlgorithm? encryptionAlgorithm = outboundSecurity.decryptionAlgorithm; @@ -76,7 +78,7 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, clientPrivateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; string decryptedEnv = regexp:replace(re `.*`, soapEnvelope.toString(), - decryptedBody); + decryptedBody); soapEnvelope = check xml:fromString(decryptedEnv); } } @@ -85,8 +87,14 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou crypto:PublicKey? serverPublicKey = outboundSecurity.verificationKey; if serverPublicKey is crypto:PublicKey { byte[] signatureData = check wssec:getSignatureData(soapEnvelope); - check wssec:verifyData((soapEnvelope//*).toString().toBytes(), - signatureData, serverPublicKey, signatureAlgorithm); + if soap12 { + check wssec:verifyData((soapEnvelope//*).toString().toBytes(), + signatureData, serverPublicKey, signatureAlgorithm); + } else { + check wssec:verifyData((soapEnvelope//*).toString().toBytes(), + signatureData, serverPublicKey, signatureAlgorithm); + } + } } return soapEnvelope; @@ -96,7 +104,7 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou } public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, string path = "", boolean soap12 = true) + map headers = {}, string path = "", boolean soap12 = true) returns xml|mime:Entity[]|Error { http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) : createSoap11HttpRequest(body, soapAction, headers); @@ -112,7 +120,7 @@ public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpCli } public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, string path = "", boolean soap12 = true) returns Error? { + map headers = {}, string path = "", boolean soap12 = true) returns Error? { http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) : createSoap11HttpRequest(body, soapAction, headers); http:Response|http:ClientError response = httpClient->post(path, req); @@ -122,7 +130,7 @@ public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient } isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAction, - map headers = {}) returns http:Request { + map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -139,7 +147,7 @@ isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAct } isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, - map headers = {}) returns http:Request { + map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -176,8 +184,8 @@ isolated function createSoap11Response(http:Response response) returns xml|mime: } public function assertUsernameToken(string envelopeString, string username, string password, - wssec:PasswordType passwordType, string body) returns error? { - string:RegExp bodyData = check regexp:fromString(body); + wssec:PasswordType passwordType, string body) returns error? { + string:RegExp bodyData = check regexp:fromString(body); test:assertTrue(envelopeString.includesMatch(bodyData)); string:RegExp usernameTokenTag = re `.*`; string:RegExp usernameTag = re `${username}`; @@ -188,7 +196,7 @@ public function assertUsernameToken(string envelopeString, string username, stri } public function assertSymmetricBinding(string envelopeString, string body) returns error? { - string:RegExp bodyData = check regexp:fromString(body); + string:RegExp bodyData = check regexp:fromString(body); test:assertTrue(envelopeString.includesMatch(bodyData)); assertSignatureWithoutX509(envelopeString); } From 6f9026aeec9971f142c559f95f83d8434f509132 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 2 Nov 2023 09:46:49 +0530 Subject: [PATCH 15/22] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 6 +++--- ballerina/Dependencies.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 9008e6f..c85d886 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.8.1" +version = "0.8.2" authors = ["Ballerina"] export=["soap", "soap.soap11", "soap.soap12"] keywords = ["soap"] @@ -19,8 +19,8 @@ graalvmCompatible = true [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "soap-native" -version = "0.8.1" -path = "../native/build/libs/soap-native-0.8.1.jar" +version = "0.8.2" +path = "../native/build/libs/soap-native-0.8.2-SNAPSHOT.jar" [[platform.java17.dependency]] groupId = "org.apache.wss4j" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 74ff3d8..8b50038 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -269,7 +269,7 @@ dependencies = [ [[package]] org = "ballerina" name = "soap" -version = "0.8.1" +version = "0.8.2" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, From 5ddaff486da6ff437565e98c9f5b34010de71a06 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 2 Nov 2023 14:43:33 +0530 Subject: [PATCH 16/22] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index c85d886..d82d21b 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.8.2" +version = "0.9.0" authors = ["Ballerina"] export=["soap", "soap.soap11", "soap.soap12"] keywords = ["soap"] @@ -19,8 +19,8 @@ graalvmCompatible = true [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "soap-native" -version = "0.8.2" -path = "../native/build/libs/soap-native-0.8.2-SNAPSHOT.jar" +version = "0.9.0" +path = "../native/build/libs/soap-native-0.9.0-SNAPSHOT.jar" [[platform.java17.dependency]] groupId = "org.apache.wss4j" From 7407153b7b8adc9d3f071e75a72408746b618a55 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 2 Nov 2023 14:52:11 +0530 Subject: [PATCH 17/22] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8b50038..1ed4692 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -269,7 +269,7 @@ dependencies = [ [[package]] org = "ballerina" name = "soap" -version = "0.8.2" +version = "0.9.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, From 74145ed5edd44abb461d9a099bef12d689d49fbb Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 2 Nov 2023 15:07:12 +0530 Subject: [PATCH 18/22] Apply suggestions from the review --- ballerina/modules/soap11/soap11.bal | 11 ++-- ballerina/modules/soap12/soap12.bal | 11 ++-- ballerina/soap_utils.bal | 27 ++++------ .../main/java/org/soap/ExecutionCallback.java | 6 ++- .../java/org/soap/{Soap11.java => Soap.java} | 23 ++++++--- native/src/main/java/org/soap/Soap12.java | 51 ------------------- spotbugs-exclude.xml | 9 ++-- 7 files changed, 49 insertions(+), 89 deletions(-) rename native/src/main/java/org/soap/{Soap11.java => Soap.java} (66%) delete mode 100644 native/src/main/java/org/soap/Soap12.java diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 5738b71..81a4ce9 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -21,7 +21,7 @@ import ballerina/http; import ballerina/mime; import ballerina/jballerina.java; -# Object for the basic SOAP client endpoint. +# Object for the basic SOAP 1.1 client endpoint. public isolated client class Client { private final http:Client soapClient; private final readonly & wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; @@ -55,12 +55,13 @@ public isolated client class Client { # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + path - The resource path - # + typeParam - Default parameter use to infer the user specified type. + # + T - Default parameter use to infer the user specified type (`xml` or `mime:Entity[]`) # + return - If successful, returns the response. Else, returns an error remote isolated function sendReceive(xml|mime:Entity[] body, string action, map headers = {}, - string path = "", typedesc typeParam = <>) - returns typeParam|Error = @java:Method { - 'class: "org.soap.Soap11" + string path = "", typedesc T = <>) + returns T|Error = @java:Method { + 'class: "org.soap.Soap", + name: "sendReceive11" } external; isolated function generateResponse(xml|mime:Entity[] body, string action, diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 9d27c55..c047063 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -21,7 +21,7 @@ import ballerina/http; import ballerina/mime; import ballerina/jballerina.java; -# Object for the basic SOAP client endpoint. +# Object for the basic SOAP 1.2 client endpoint. public isolated client class Client { private final http:Client soapClient; private final readonly & wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; @@ -55,12 +55,13 @@ public isolated client class Client { # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + path - The resource path - # + typeParam - Default parameter use to infer the user specified type. + # + T - Default parameter use to infer the user specified type (`xml` or `mime:Entity[]`) # + return - If successful, returns the response. Else, returns an error remote isolated function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {}, - string path = "", typedesc typeParam = <>) - returns typeParam|Error = @java:Method { - 'class: "org.soap.Soap12" + string path = "", typedesc T = <>) + returns T|Error = @java:Method { + 'class: "org.soap.Soap", + name: "sendReceive12" } external; isolated function generateResponse(xml|mime:Entity[] body, string? action = (), diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 6338234..0e36532 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -104,23 +104,24 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou } public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, string path = "", boolean soap12 = true) + map headers = {}, string path = "", boolean soap12 = true) returns xml|mime:Entity[]|Error { http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) : createSoap11HttpRequest(body, soapAction, headers); do { http:Response response = check httpClient->post(path, req); if soap12 { - return check createSoap12Response(response); + return check createSoapResponse(response); } - return check createSoap11Response(response); + return check createSoapResponse(response); } on fail var err { return error Error(SOAP_RESPONSE_ERROR, err); } } public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, string path = "", boolean soap12 = true) returns Error? { + map headers = {}, string path = "", boolean soap12 = true) + returns Error? { http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) : createSoap11HttpRequest(body, soapAction, headers); http:Response|http:ClientError response = httpClient->post(path, req); @@ -130,7 +131,7 @@ public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient } isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAction, - map headers = {}) returns http:Request { + map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -147,7 +148,7 @@ isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAct } isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, - map headers = {}) returns http:Request { + map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -165,20 +166,10 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc return req; } -isolated function createSoap12Response(http:Response response) returns xml|mime:Entity[]|error { - xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - mime:Entity[]|http:ClientError payload = response.getBodyParts(); - if payload !is mime:Entity[] { - return check response.getXmlPayload(); - } - return payload; -} - -isolated function createSoap11Response(http:Response response) returns xml|mime:Entity[]|error { - xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; +isolated function createSoapResponse(http:Response response) returns xml|mime:Entity[]|error { mime:Entity[]|http:ClientError payload = response.getBodyParts(); if payload !is mime:Entity[] { - return check response.getXmlPayload(); + return response.getXmlPayload(); } return payload; } diff --git a/native/src/main/java/org/soap/ExecutionCallback.java b/native/src/main/java/org/soap/ExecutionCallback.java index 8005113..454ac35 100644 --- a/native/src/main/java/org/soap/ExecutionCallback.java +++ b/native/src/main/java/org/soap/ExecutionCallback.java @@ -36,6 +36,10 @@ public void notifySuccess(Object o) { @Override public void notifyFailure(BError bError) { - this.future.complete(bError); + bError.printStackTrace(); + // Service level `panic` is captured in this method. + // Since, `panic` is due to a critical application bug or resource exhaustion we need to exit the application. + // Please refer: https://github.com/ballerina-platform/ballerina-standard-library/issues/2714 + System.exit(1); } } diff --git a/native/src/main/java/org/soap/Soap11.java b/native/src/main/java/org/soap/Soap.java similarity index 66% rename from native/src/main/java/org/soap/Soap11.java rename to native/src/main/java/org/soap/Soap.java index 90d7375..fe1e33f 100644 --- a/native/src/main/java/org/soap/Soap11.java +++ b/native/src/main/java/org/soap/Soap.java @@ -29,8 +29,7 @@ import static org.wssec.ModuleUtils.getModule; - -public class Soap11 { +public class Soap { private static final String REMOTE_FUNCTION = "generateResponse"; public static final StrandMetadata REMOTE_EXECUTION_STRAND = new StrandMetadata( getModule().getOrg(), @@ -38,14 +37,26 @@ public class Soap11 { getModule().getMajorVersion(), REMOTE_FUNCTION); - public static Object sendReceive(Environment env, BObject soap11, Object body, BString action, - BMap headers, BString path, BTypedesc typeParam) { + public static Object sendReceive11(Environment env, BObject soap11, Object body, BString action, + BMap headers, BString path, BTypedesc typeDesc) { Future future = env.markAsync(); ExecutionCallback executionCallback = new ExecutionCallback(future); - UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_JSON_ARRAY, - PredefinedTypes.TYPE_ERROR); + UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_ANYDATA_ARRAY, + PredefinedTypes.TYPE_ERROR); Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; env.getRuntime().invokeMethodAsyncConcurrently(soap11, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, + executionCallback, null, typeUnion, arguments); + return null; + } + + public static Object sendReceive12(Environment env, BObject soap12, Object body, Object action, + BMap headers, BString path, BTypedesc typeDesc) { + Future future = env.markAsync(); + ExecutionCallback executionCallback = new ExecutionCallback(future); + UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_ANYDATA_ARRAY, + PredefinedTypes.TYPE_ERROR); + Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; + env.getRuntime().invokeMethodAsyncConcurrently(soap12, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, executionCallback, null, typeUnion, arguments); return null; } diff --git a/native/src/main/java/org/soap/Soap12.java b/native/src/main/java/org/soap/Soap12.java deleted file mode 100644 index 75cacf7..0000000 --- a/native/src/main/java/org/soap/Soap12.java +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. -// -// WSO2 LLC. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.soap; - -import io.ballerina.runtime.api.Environment; -import io.ballerina.runtime.api.Future; -import io.ballerina.runtime.api.PredefinedTypes; -import io.ballerina.runtime.api.async.StrandMetadata; -import io.ballerina.runtime.api.creators.TypeCreator; -import io.ballerina.runtime.api.types.UnionType; -import io.ballerina.runtime.api.values.BMap; -import io.ballerina.runtime.api.values.BObject; -import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.api.values.BTypedesc; - -import static org.wssec.ModuleUtils.getModule; - -public class Soap12 { - private static final String REMOTE_FUNCTION = "generateResponse"; - public static final StrandMetadata REMOTE_EXECUTION_STRAND = new StrandMetadata( - getModule().getOrg(), - getModule().getName(), - getModule().getMajorVersion(), - REMOTE_FUNCTION); - - public static Object sendReceive(Environment env, BObject soap12, Object body, Object action, - BMap headers, BString path, BTypedesc typeParam) { - Future future = env.markAsync(); - ExecutionCallback executionCallback = new ExecutionCallback(future); - UnionType typeUnion = TypeCreator.createUnionType(PredefinedTypes.TYPE_XML, PredefinedTypes.TYPE_JSON_ARRAY, - PredefinedTypes.TYPE_ERROR); - Object[] arguments = new Object[]{body, true, action, true, headers, true, path, true}; - env.getRuntime().invokeMethodAsyncConcurrently(soap12, REMOTE_FUNCTION, null, REMOTE_EXECUTION_STRAND, - executionCallback, null, typeUnion, arguments); - return null; - } -} diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 26bf2bc..14fcc1f 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -1,7 +1,7 @@ - + + + + From 81f0bf089b2cf93c34f43ed495b2cd4c7e5ffbb1 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 2 Nov 2023 15:11:31 +0530 Subject: [PATCH 19/22] Update documentation to adhere new changes --- README.md | 6 +++--- ballerina/Module.md | 6 +++--- ballerina/Package.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2214ffd..7d4d0d3 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` @@ -172,7 +172,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` @@ -213,7 +213,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` diff --git a/ballerina/Module.md b/ballerina/Module.md index 3da335a..8bd2916 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -47,7 +47,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` @@ -162,7 +162,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` @@ -202,7 +202,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` diff --git a/ballerina/Package.md b/ballerina/Package.md index 685dae7..7eba60f 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -162,7 +162,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` From cc94acbf9b4e207de78305183521d5ad05c4d40a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 2 Nov 2023 15:15:35 +0530 Subject: [PATCH 20/22] Bump the package version to 0.9.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 703bea6..1cb266f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=0.8.2-SNAPSHOT +version=0.9.0-SNAPSHOT checkstylePluginVersion=10.12.0 spotbugsPluginVersion=5.0.14 From c50a4a497e9cee3d7f4aabca4e126cb7582690c0 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 3 Nov 2023 10:17:25 +0530 Subject: [PATCH 21/22] Apply suggestions from the review --- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap12/soap12.bal | 2 +- .../java/{org => io/ballerina/lib}/soap/ExecutionCallback.java | 2 +- native/src/main/java/{org => io/ballerina/lib}/soap/Soap.java | 2 +- spotbugs-exclude.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename native/src/main/java/{org => io/ballerina/lib}/soap/ExecutionCallback.java (98%) rename native/src/main/java/{org => io/ballerina/lib}/soap/Soap.java (99%) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 81a4ce9..a7eeb8e 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -60,7 +60,7 @@ public isolated client class Client { remote isolated function sendReceive(xml|mime:Entity[] body, string action, map headers = {}, string path = "", typedesc T = <>) returns T|Error = @java:Method { - 'class: "org.soap.Soap", + 'class: "io.ballerina.lib.soap.Soap", name: "sendReceive11" } external; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index c047063..d69833a 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -60,7 +60,7 @@ public isolated client class Client { remote isolated function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {}, string path = "", typedesc T = <>) returns T|Error = @java:Method { - 'class: "org.soap.Soap", + 'class: "io.ballerina.lib.soap.Soap", name: "sendReceive12" } external; diff --git a/native/src/main/java/org/soap/ExecutionCallback.java b/native/src/main/java/io/ballerina/lib/soap/ExecutionCallback.java similarity index 98% rename from native/src/main/java/org/soap/ExecutionCallback.java rename to native/src/main/java/io/ballerina/lib/soap/ExecutionCallback.java index 454ac35..4f17f34 100644 --- a/native/src/main/java/org/soap/ExecutionCallback.java +++ b/native/src/main/java/io/ballerina/lib/soap/ExecutionCallback.java @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. -package org.soap; +package io.ballerina.lib.soap; import io.ballerina.runtime.api.Future; import io.ballerina.runtime.api.async.Callback; diff --git a/native/src/main/java/org/soap/Soap.java b/native/src/main/java/io/ballerina/lib/soap/Soap.java similarity index 99% rename from native/src/main/java/org/soap/Soap.java rename to native/src/main/java/io/ballerina/lib/soap/Soap.java index fe1e33f..eb76da0 100644 --- a/native/src/main/java/org/soap/Soap.java +++ b/native/src/main/java/io/ballerina/lib/soap/Soap.java @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. -package org.soap; +package io.ballerina.lib.soap; import io.ballerina.runtime.api.Environment; import io.ballerina.runtime.api.Future; diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 14fcc1f..e22fda1 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -17,7 +17,7 @@ --> - + From 14d1d137c0db3e9ae9ef1bbf1fbf860c4635fd00 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 3 Nov 2023 11:25:05 +0530 Subject: [PATCH 22/22] Fix formatting in payloads --- .../soap11/tests/http_soap_service.bal | 55 +++++++++++-------- .../soap12/tests/http_soap_service.bal | 32 +++++++---- 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index 72eb50e..98f561f 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -13,7 +13,6 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. - import ballerina/crypto; import ballerina/http; import ballerina/mime; @@ -24,7 +23,7 @@ const crypto:KeyStore serverKeyStore = { password: KEY_PASSWORD }; crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, - KEY_PASSWORD); + KEY_PASSWORD); crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); service / on new http:Listener(9090) { @@ -59,18 +58,24 @@ service / on new http:Listener(9090) { xml payload = check (check request.getBodyParts())[0].getXml(); xml applyOutboundConfig = check soap:applyOutboundConfig( { - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload, false); + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, + payload, + false + ); xml securedEnv = check soap:applySecurityPolicies( { - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig, false); + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, + applyOutboundConfig, + false + ); http:Response response = new; mime:Entity[] mtomMessage = []; mime:Entity envelope = new; @@ -87,18 +92,24 @@ service / on new http:Listener(9090) { xml payload = check request.getXmlPayload(); xml applyOutboundConfig = check soap:applyOutboundConfig( { - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload, false); + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, + payload, + false + ); xml securedEnv = check soap:applySecurityPolicies( { - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig, false); + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, + applyOutboundConfig, + false + ); http:Response response = new; response.setPayload(securedEnv); return response; diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index 0191aaf..f4cc2bd 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -63,14 +63,18 @@ service / on new http:Listener(9090) { signatureAlgorithm: soap:RSA_SHA256, decryptionAlgorithm: soap:RSA_ECB, decryptionKey: serverPrivateKey - }, payload); + }, + payload + ); xml securedEnv = check soap:applySecurityPolicies( { signatureAlgorithm: soap:RSA_SHA256, encryptionAlgorithm: soap:RSA_ECB, signatureKey: serverPrivateKey, encryptionKey: clientPublicKey - }, applyOutboundConfig); + }, + applyOutboundConfig + ); http:Response response = new; response.setPayload(securedEnv); return response; @@ -80,18 +84,22 @@ service / on new http:Listener(9090) { xml payload = check (check request.getBodyParts())[0].getXml(); xml applyOutboundConfig = check soap:applyOutboundConfig( { - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload); + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, + payload + ); xml securedEnv = check soap:applySecurityPolicies( { - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig); + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, + applyOutboundConfig + ); http:Response response = new; mime:Entity[] mtomMessage = []; mime:Entity envelope = new;