Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix action not set in the 'content-type' header in SOAP 1.2 #116

Merged
merged 11 commits into from
Dec 6, 2023
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -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"]
Expand All @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
Expand Down Expand Up @@ -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"},
Expand Down
16 changes: 15 additions & 1 deletion ballerina/modules/soap12/tests/http_soap_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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<string> 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;
Expand Down
105 changes: 56 additions & 49 deletions ballerina/modules/soap12/tests/soap12_client_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding/"><soap:Body><quer:Add xmlns:quer="http://tempuri.org/"><quer:intA>2</quer:intA><quer:intB>3</quer:intB></quer:Add></soap:Body></soap:Envelope>`;

xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getActionPayload");
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding/"><soap:Body><quer:Add xmlns:quer="http://tempuri.org/"><quer:intA>2</quer:intA><quer:intB>3</quer:intB></quer:Add></soap:Body></soap:Envelope>`;
test:assertEquals(response, expected);
}

@test:Config {
groups: ["soap12", "send_receive"]
}
Expand All @@ -102,14 +114,14 @@ function testSendReceive12() returns error? {
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml response = check soapClient->sendReceive(body);

xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AddResponse xmlns="http://tempuri.org/"><AddResult>5</AddResult></AddResponse></soap:Body></soap:Envelope>`;
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");
Expand Down Expand Up @@ -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 `<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
Expand All @@ -201,19 +214,33 @@ function testSendReceive12WithHeaders() returns error? {
</soap:Body>
</soap:Envelope>`;

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("<soap@envelope>");
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("<image1>");
mtomMessage.push(bytesPart);

xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AddResponse xmlns="http://tempuri.org/"><AddResult>5</AddResult></AddResponse></soap:Body></soap:Envelope>`;
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 `<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
Expand All @@ -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 `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AddResponse xmlns="http://tempuri.org/"><AddResult>5</AddResult></AddResponse></soap:Body></soap:Envelope>`;
test:assertEquals(response, expected);
Expand All @@ -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 `<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Body>
<quer:Add xmlns:quer="http://tempuri.org/">
<quer:intA>2</quer:intA>
<quer:intB>3</quer:intB>
</quer:Add>
</soap:Body>
</soap:Envelope>`;

Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL");

xml response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]});
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><AddResponse xmlns="http://tempuri.org/"><AddResult>5</AddResult></AddResponse></soap:Body></soap:Envelope>`;
test:assertEquals(response, expected);
}

@test:Config {
groups: ["soap12"]
}
Expand Down Expand Up @@ -340,7 +345,7 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? {
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml response = check soapClient->sendReceive(body);
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:MustUnderstand</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.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()
Expand Down Expand Up @@ -374,7 +379,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? {
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml response = check soapClient->sendReceive(body);
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:MustUnderstand</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.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()
Expand Down Expand Up @@ -421,12 +426,13 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? {
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:MustUnderstand</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.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()</soap:Text></soap:Reason></soap:Fault></soap:Body></soap:Envelope>`;
xml response = check soapClient->sendReceive(body);
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Sender</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.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&amp; abortProcessing)</soap:Text></soap:Reason><soap:Detail/></soap:Fault></soap:Body></soap:Envelope>`;

test:assertEquals(response.toString(), expected.toString());
}
Expand Down Expand Up @@ -467,12 +473,13 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? {
</quer:Add>
</soap:Body>
</soap:Envelope>`;
xml response = check soapClient->sendReceive(body, "http://tempuri.org/Add");
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:MustUnderstand</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.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()</soap:Text></soap:Reason></soap:Fault></soap:Body></soap:Envelope>`;
xml response = check soapClient->sendReceive(body);
xml expected = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Sender</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.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&amp; abortProcessing)</soap:Text></soap:Reason><soap:Detail/></soap:Fault></soap:Body></soap:Envelope>`;
test:assertEquals(response.toString(), expected.toString());
}

Expand Down Expand Up @@ -517,7 +524,7 @@ function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? {
}
);
xml body = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding/"><soap:Body><quer:Add xmlns:quer="http://tempuri.org/"><quer:intA>2</quer:intA><quer:intB>3</quer:intB></quer:Add></soap:Body></soap:Envelope>`;
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 `<soap:Body><quer:Add xmlns:quer="http://tempuri.org/"><quer:intA>2</quer:intA><quer:intB>3</quer:intB></quer:Add></soap:Body>`);
}

Expand All @@ -543,7 +550,7 @@ function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error?
);

xml body = xml `<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><soap:Body><quer:Add xmlns:quer="http://tempuri.org/"><quer:intA>2</quer:intA><quer:intB>3</quer:intB></quer:Add></soap:Body></soap:Envelope>`;
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 `<soap:Body><quer:Add xmlns:quer="http://tempuri.org/"><quer:intA>2</quer:intA><quer:intB>3</quer:intB></quer:Add></soap:Body>`);
}

Expand Down
17 changes: 14 additions & 3 deletions ballerina/soap_utils.bal
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading