I am looking to check a value that returns in the ResponseBody from a SOAP Web Service.
Here is a sample ResponseBody from Web Service:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns5:getUserResponse xmlns:ns5="http://<someservice>" xmlns:ns3="java:com.mywebservice">
<ns3:resultCode>0</ns3:resultCode>
</S:Body>
</S:Envelope>
I have the following:
....//snipped for brevity
.check(regex("""<ns3:resultCode>(\d*)</ns3:resultCode""").saveAs("resCode"))
.check("""${resCode}""".in(0 to 200))
....//snipped for brevity
I get an error message on the fact that .in isn't available for a String type but I am unsure how else to validate that the response of an xml contains particular values.
Any assistance would be awesome, and anything else needed I should more than happily oblige. Thanks in advance.
EDIT:
I forgot to mention that I am using gatling version 2.0.0-M3a - Thanks in advance.
With current 2.0.0-SNAPSHOT, that's:
.check(regex("""<ns3:resultCode>(\d*)</ns3:resultCode""")
.transform(_.toInt)
.in(0 to 200))
With 2M3a, that's:
.check(regex("""<ns3:resultCode>(\d*)</ns3:resultCode""")
.transform(_.map(_.toInt))
.in(0 to 200))
Related
I'm trying to make a call to a 3rd party webservice using Sage X3 scripts, I'm using the func ASYRWEBSER.EXEC_HTTP which is working fine and it's calling the webservice and receiving the answer
The Answer:
<s:Envelope
xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
<s:Body>
<CreateShipmentResponse
xmlns=\"http://tempuri.org/\">
<CreateShipmentResult
xmlns:a=\"http://schemas.datacontract.org/2004/07/CTTExpressoWS\"
xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">
<a:ErrorsList/>
<a:ShipmentData>
<a:ShipmentDataOutput>
<a:ClientReference>teste</a:ClientReference>
<a:DocumentsList>
</a:DocumentsList>
<a:FirstObject>DB112320353PT</a:FirstObject>
<a:LabelList>
<a:LabelData>
<a:BestEncoding>65001</a:BestEncoding>
<a:FileName>ETI</a:FileName>
<a:Label>^XA
\n</a:Label>
</a:LabelData>
</a:LabelList>
<a:LastObject>DB112320353PT</a:LastObject>
<a:OriginalObjectID i:nil=\"true\"/>
</a:ShipmentDataOutput>
</a:ShipmentData>
<a:Status>Success</a:Status>
</CreateShipmentResult>
</CreateShipmentResponse>
</s:Body>
</s:Envelope>
My problem is that I don't know how to get the XML fields I need in X3 Scripts, can anyone point me in the right direction?
I need to get the <a:LastObject>, the <a:Status> and the <a:LabelList><a:LabelData> of the response.
Maybe I am a little late, but in case you did not solve it yet: You get the response in a clbfile variable (last parameter of EXEC_HTTP - Funprog EXEC_HTTP(HEADERCOD, HEADERVAL, DATA, RESHEAD, RESBODY)).
Here are a few options to parse the RESBODY clbfile:
Parse the content directly in 4gl.
Module in nodeJS (custom module)
Executable called by "System" instruction
I have problems to get SOAP request through Zeep, I get a (client) validation error... I have also tested with SoapUI and that does NOT give me the same validation error...
The specification below is from the server... Based on that specification, the OrderStatus and SynchStatus are needed to perform the request.
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/ xmlns:web="WebServiceProvider">
<soapenv:Header/>
<soapenv:Body>
<web:Order_Get>
<!--Optional:-->
<web:orderOptions>
<web:FromDate>?</web:FromDate>
<web:ToDate>?</web:ToDate>
<web:OrderStatus>?</web:OrderStatus>
<web:SynchStatus>?</web:SynchStatus>
<!--Optional:-->
<web:OrderNumber>?</web:OrderNumber>
<web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
<web:PaymentStatus>?</web:PaymentStatus>
</web:orderOptions>
</web:Order_Get>
</soapenv:Body>
</soapenv:Envelope>
However, executing this from the SoapUI without OrderStatus and SynchStatus will give me a list of all the orders for the specified dates:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="WebServiceProvider">
<soapenv:Header/>
<soapenv:Body>
<web:Order_Get>
<web:orderOptions>
<web:FromDate>2021-03-30</web:FromDate>
<web:ToDate>2021-03-31</web:ToDate>
</web:orderOptions>
</web:Order_Get>
</soapenv:Body>
</soapenv:Envelope>
I want to do the same with Zeep (https://github.com/mvantellingen/python-zeep) but the client validation fails...
I initiate the request with the following code:
api_url = 'https://abc.se/Webservice20/v3.0/webservice.asmx?WSDL'
session.auth = HTTPDigestAuth(username, password)
api = Client(api_url, transport=Transport(session=session))
And then I try to execute the following request:
order_options = {
'FromDate': '2021-03-30',
'ToDate': '2021-03-31',
}
orders = api.service.Order_Get(orderOptions=order_options)
This will result in the following error:
zeep.exceptions.ValidationError: Missing element OrderStatus (Order_Get.orderOptions.OrderStatus)
If I add OrderStatus to the request, I will get a validation error saying that SynchStatus is missing. When that has been added as well, the request is sent to the server.
I.e. it seems like the zeep client is more strict with regards to validating the data in the request than what the server is... Is there a way to force the client to skip this validation?
Many thanks in advance!
Searched a bit more and found a workaround in this post: Getting zeep.exceptions.ValidationError: Missing element for method that worked with suds
So the solution in my case looks like this:
from zeep import xsd
...
order_options = {
'FromDate': '2021-03-30',
'ToDate': '2021-03-31',
'OrderStatus': xsd.SkipValue,
'SynchStatus': xsd.SkipValue,
}
response = api.service.Order_Get(orderOptions=order_options)
This will block zeep from doing client side validation of the parameters OrderStatus and SynchStatus.
it seems like the zeep client is more strict with regards to validating the data in the request than what the server is...
Looks like it.
Looking at the request SoapUI generates based on the WSDL, the two fields you mention are mandatory:
<web:orderOptions>
<web:FromDate>?</web:FromDate>
<web:ToDate>?</web:ToDate>
<web:OrderStatus>?</web:OrderStatus>
<web:SynchStatus>?</web:SynchStatus>
<!--Optional:-->
<web:OrderNumber>?</web:OrderNumber>
<web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
<web:PaymentStatus>?</web:PaymentStatus>
</web:orderOptions>
So the error that the zeep client displays is correct. Zeep inspects the WSDL and generates the corresponding code to use the types in the contract. Your WSDL contract says that OrderStatus and SynchStatus are mandatory. The fact that the server doesn't validate them shows a problem: the web service isn't respecting it's own documented contract
The WSDL and the behavior of the web service should be the same. I suggest you contact the web service owners and ask about this behavior. It might be a validation missing on the server and what you get is just some side effect of that, or the behavior is intentional but someone forgot to update the WSDL to say that you can also make the call without those parameters.
Meanwhile, the workaround is very simple. Download the WSDL, change it to make the two fields optional, then feed this changed WSDL to zeep for it to generate the code, instead of using the original WSDL. You should however clarify this with the web service provider. If it's indeed a neglect of someone, this might be spotted at some point and fixed, making your workaround call fail a server validation because of the missing fields.
This question is very specific. If CUCM, AXL and SOAP doesn't tell you anything, there's no need to read further. Except you're interested.
Has anyone been successful at wsimporting the current WSDL file for Cisco AXL and supporting the AddTransPattern-Request? I'm talking about version 8.5 or "current" (as in Cisco UCM 8.6.2).
The import was successful, but adding a translation pattern doesn't work anymore.
I tested it by writing my SOAP request by hand, using soapUI in eclipse.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/8.5">
<soapenv:Header/>
<soapenv:Body>
<ns:addTransPattern sequence="?">
<transPattern>
<pattern>MYPATTERN</pattern>
<description>MYDESCRIPTION</description>
<routePartitionName>MYPARTITION</routePartitionName>
<calledPartyTransformationMask>MYDESTINATION</calledPartyTransformationMask>
<provideOutsideDialtone>false</provideOutsideDialtone>
<callingSearchSpaceName>MYCALLINGSEARCHSPACE</callingSearchSpaceName>
</transPattern>
</ns:addTransPattern>
</soapenv:Body>
The response is as follows:
<axlcode>-391</axlcode>
<axlmessage>Cannot insert a null into column (numplan.tkpatternusage).</axlmessage>
<request>addTransPattern</request>
soapUI tells me that putting usage is optional. Even if I put a value for usage, e.g. <usage>3</usage>, it tells me the value wouldn't exist even though I know it does.
Any idea is appreciated
Finally, I figured out what was wrong.
The value for <usage> needs to be a string, like in this case Translation. Then it works without any problem.
I'm trying to implement a client for National Rail Enquiries' SOAP Service (http://www.livedepartureboards.co.uk/ldbws/).
I stick the WSDL (http://realtime.nationalrail.co.uk/ldbws/wsdl.aspx) into http://soapclient.com/soaptest.html, but I get back the error message "Unable to handle request without a valid action parameter. Please supply a valid soap action."; what on earth should the action be?
Thanks,
Stewart
edit:
I just used soapclient.com as a quick example. In my software, I send the following XML; I still get that I'm missing an action.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://thalesgroup.com/RTTI/2008-02-20/ldb/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:ldbt2="http://thalesgroup.com/RTTI/2008-02-20/ldb/types" xmlns:ldbt="http://thalesgroup.com/RTTI/2007-10-10/ldb/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ct="http://thalesgroup.com/RTTI/2007-10-10/ldb/commontypes" >
<SOAP-ENV:Body>
<ldbt2:GetDepartureBoardRequest xmlns:ldbt2="http://thalesgroup.com/RTTI/2008-02-20/ldb/" >
<ldbt2:numRows>5</ldbt2:numRows>
<ldbt2:crs>WAT</ldbt2:crs>
<ldbt2:filterCrs>GLD</ldbt2:filterCrs>
<ldbt2:filterType>to</ldbt2:filterType>
<ldbt2:timeOffset>0</ldbt2:timeOffset>
</ldbt2:GetDepartureBoardRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
If its a SOAP 1.1 service then you will also need to include a SOAPAction HTTP header field:
http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
I have come across exactly the same problem when trying to write a client for the National Rail SOAP service with Perl.
The problem was caused because the Perl module that I'm using 'SOAP::Lite' inserts a '#' in the SOAPAction header ...
SOAPAction: "http://thalesgroup.com/RTTI/2008-02-20/ldb/#GetDepartureBoard"
This is not interpreted correctly by .NET servers. I found this out from Example 3-19 in O'Reilly's Programming Web Services with SOAP . The solution was given below in section 3-20, namely you need to explicitly specify the format of the header with the 'on_action' method.
print SOAP::Lite
-> uri('urn:Example1')
-> on_action(sub{sprintf '%s/%s', #_ })
-> proxy('http://localhost:8080/helloworld/example1.asmx')
-> sayHello($name)
-> result . "\n\n";
My guess is that soapclient.com is using SOAP::Lite behind the scenes and so are hitting the same problem when talking to National Rail.
The solution is to write your own client so that you have control over the format of the SOAPAction header ... but you've probably done that already.
SOAPAction is required in SOAP 1.1 but can be empty ("").
See https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
"The header field value of empty string ("") means that the intent of the SOAP message is provided by the HTTP Request-URI."
Try setting SOAPAction=""
When soapAction is missing in the SOAP 1.2 request (and many clients do not set it, even when it is specified in WSDL), some app servers (eg. jboss) infer the "actual" soapAction from {xsd:import namespace}+{wsdl:operation name}.
So, to make the inferred "actual" soapAction match the expected soapAction, you can set the expected soapAction to {xsd:import namespace}+{wsdl:operation name} in your WS definition (#WebMethod(action=...) for Java EE)
Eg. for a typical Java EE case, this helps (not the Stewart's case, National Rail WS has 'soapAction' set):
#WebMethod(action = "http://packagename.of.your.webservice.class.com/methodName")
If you cannot change the server, you will have to force client to fill soapAction.
I've just spent a while trying to get this to work an have a written a Ruby gem that accesses the API. You can read more on it's project page.
This is working code in Ruby:
require 'savon'
client = Savon::Client.new do
wsdl.document = "http://realtime.nationalrail.co.uk/LDBWS/wsdl.aspx"
end
response = client.request 'http://thalesgroup.com/RTTI/2012-01-13/ldb/GetDepartureBoard' do
namespaces = {
"xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema"
}
soap.xml do |xml|
xml.soap(:Envelope, namespaces) do |xml|
xml.soap(:Header) do |xml|
xml.AccessToken do |xml|
xml.TokenValue('ENTER YOUR TOKEN HERE')
end
end
xml.soap(:Body) do |xml|
xml.GetDepartureBoardRequest(xmlns: "http://thalesgroup.com/RTTI/2012-01-13/ldb/types") do |xml|
xml.numRows(10)
xml.crs("BHM")
xml.filterCrs("BHM")
xml.filterType("to")
end
end
end
end
end
p response.body
Hope that's helpful for someone!
We put together Web Services on Windows Server and were trying to connect with PHP on Apache. We got the same error. The issue ended up being different versions of the Soap client on the different servers. Matching the SOAP versions in the options on both servers solved the issue in our case.
the service have 4 operations:
1. GetServiceDetails
2. GetArrivalBoard
3. GetDepartureBoard
4. GetArrivalDepartureBoard
I have solved this problem, in Java Code, adding:
MimeHeaders headers = message.getMimeHeaders();
headers.addHeader("SOAPAction", endpointURL);
I'm trying to modify the soapenv:Header to include addressing in my soap request
my $header=SOAP::Header->name("Header")->prefix("soap")->uri("http://www.w3.org/2005/08/addressing");
When I send the request:
print $soap->call($header, $security->value(\$userToken, $action, $message))->result;
I receive the following...
<"soap:Header soap:Header xmlns:soap="http://www.w3.org/2005/08/addressing" />
I need to try and override the original <soap:Header> I need to do the same for the <soap:Envelope>
Would be greatly appreciated if someone could help out :-)
The first argument to "call" is the method name, not the header.
There is a class in SOAP::Lite called SOAP::Lite::Packager. Look at the "Heades_http" Method. I think that is what you want.