diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index b6306cd..543f588 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.9.0" +version = "0.10.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.9.0" -path = "../native/build/libs/soap-native-0.9.0.jar" +version = "0.10.0" +path = "../native/build/libs/soap-native-0.10.0-SNAPSHOT.jar" [[platform.java17.dependency]] groupId = "org.apache.wss4j" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 1ed4692..1944db6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.1" +version = "2.10.4" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -269,7 +269,7 @@ dependencies = [ [[package]] org = "ballerina" name = "soap" -version = "0.9.0" +version = "0.10.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index f4cc2bd..3bce134 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -24,7 +24,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) { @@ -48,6 +48,20 @@ service / on new http:Listener(9090) { return response; } + resource function post getActionPayload(http:Request request) returns http:Response|error { + string[] headers = check request.getHeaders(mime:CONTENT_TYPE); + mime:MediaType mediaHeader = check mime:getMediaType(headers[0]); + map actionMap = mediaHeader.parameters; + string action = actionMap.get("action"); + if action == "http://tempuri.org/Add" { + xml payload = check request.getXmlPayload(); + http:Response response = new; + response.setPayload(payload); + return response; + } + return error("Invalid action is found"); + } + resource function post getSamePayload(http:Request request) returns http:Response|error { xml payload = check request.getXmlPayload(); http:Response response = new; diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 331848f..42334b7 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -87,6 +87,18 @@ function testSendOnlyError12() returns error? { test:assertTrue(response is Error); } +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceive12WithAction() returns error? { + Client soapClient = check new ("http://localhost:9090"); + xml body = xml `23`; + + xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getActionPayload"); + xml expected = xml `23`; + test:assertEquals(response, expected); +} + @test:Config { groups: ["soap12", "send_receive"] } @@ -102,14 +114,14 @@ function testSendReceive12() returns error? { `; - xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body); xml expected = xml `5`; test:assertEquals(response, expected); } @test:Config { - groups: ["soap12", "send_receive"] + groups: ["soap12", "send_receive", "mime"] } function testSendReceive12Mime() returns error? { Client soapClient = check new ("http://localhost:9090"); @@ -187,9 +199,10 @@ function testSendReceive12WithMime2() returns error? { } @test:Config { - groups: ["soap12", "send_receive"] + groups: ["soap12", "send_receive", "mime", "h"] } -function testSendReceive12WithHeaders() returns error? { +function testSendReceive12MimeWithoutAction() returns error? { + Client soapClient = check new ("http://localhost:9090"); xml body = xml ` @@ -201,19 +214,33 @@ function testSendReceive12WithHeaders() returns error? { `; - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); - xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", - {foo: ["bar1", "bar2"]}); + 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 expected = xml `5`; - test:assertEquals(response, expected); + mime:Entity[] response = check soapClient->sendReceive(mtomMessage, path = "/getMimePayload"); + test:assertEquals(response[0].getXml(), check mtomMessage[0].getXml()); } @test:Config { groups: ["soap12", "send_receive"] } -function testSendReceive12WithoutSoapAction() returns error? { +function testSendReceive12WithHeaders() returns error? { xml body = xml ` @@ -227,7 +254,7 @@ function testSendReceive12WithoutSoapAction() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml response = check soapClient->sendReceive(body); + xml response = check soapClient->sendReceive(body, headers = {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); @@ -253,28 +280,6 @@ function testSendOnly12WithoutSoapAction() returns error? { check soapClient->sendOnly(body); } -@test:Config { - groups: ["soap12", "send_receive"] -} -function testSendReceive12IncludingHeadersWithoutSoapAction() returns error? { - xml body = xml ` - - - 2 - 3 - - - `; - - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - - xml response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]}); - xml expected = xml `5`; - test:assertEquals(response, expected); -} - @test:Config { groups: ["soap12"] } @@ -340,7 +345,7 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? { `; - xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body); 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() @@ -374,7 +379,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { `; - xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml response = check soapClient->sendReceive(body); 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() @@ -421,12 +426,13 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { `; - 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() - at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + xml response = check soapClient->sendReceive(body); + xml expected = xml `soap:SenderSystem.Web.Services.Protocols.SoapException: Unable to handle request without a valid action parameter. Please supply a valid soap action. + at System.Web.Services.Protocols.Soap12ServerProtocolHelper.RouteRequest() + at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message) + at System.Web.Services.Protocols.SoapServerProtocol.Initialize() + at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response) + at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)`; test:assertEquals(response.toString(), expected.toString()); } @@ -467,12 +473,13 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { `; - 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() - at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + xml response = check soapClient->sendReceive(body); + xml expected = xml `soap:SenderSystem.Web.Services.Protocols.SoapException: Unable to handle request without a valid action parameter. Please supply a valid soap action. + at System.Web.Services.Protocols.Soap12ServerProtocolHelper.RouteRequest() + at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message) + at System.Web.Services.Protocols.SoapServerProtocol.Initialize() + at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response) + at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)`; test:assertEquals(response.toString(), expected.toString()); } @@ -517,7 +524,7 @@ 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`); } @@ -543,7 +550,7 @@ 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/soap_utils.bal b/ballerina/soap_utils.bal index 0e36532..e0dc49e 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -152,13 +152,24 @@ 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 { - req.addHeader(SOAP_ACTION, soapAction); + mime:MediaType|mime:InvalidContentTypeError mediaType; + if body is xml { + mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); + } else { + mediaType = mime:getMediaType(mime:MULTIPART_MIXED); + } + if mediaType is mime:MediaType { + mediaType.parameters = {"action": string `"${soapAction}"`}; + req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); + } + } else if body is xml { + req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); + } else { + req.setHeader(mime:CONTENT_TYPE, mime:MULTIPART_MIXED); } foreach string key in headers.keys() { req.addHeader(key, headers[key].toBalString()); diff --git a/gradle.properties b/gradle.properties index 95178f8..350f148 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=0.9.1-SNAPSHOT +version=0.10.0-SNAPSHOT checkstylePluginVersion=10.12.0 spotbugsPluginVersion=5.0.14