I'm trying to create stub in wirkmock. But it's show 'request not match' when I hit the endpoint
it's work when I use a simple check
In code:
stubFor(get(urlEqualTo("/v1/test.svc"))
.withHeader("Content-Type", equalTo("application/xml"))
.withRequestBody(containing("<b:Name>Test</b:Name>"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/xml")
.withBody("Passed")));
Request:
endpoint
http://{{url}}/v1/test.svc
header
Content-Type:application/xml
body
<test xmlns="http://abc.example.com">
<request xmlns:b="http://abc.example.com/b" xmlns:i="http://abc.example.com/i">
<b:Name>Test</b:Name>
<b:Age>18</b:Age>
<b:Count>2020</b:Count>
</request>
</test>
Result:
Passed
But it's not working when I try to use xpath for check some values
In code:
stubFor(get(urlEqualTo("/paymentapi/paymentservice.svc"))
.withHeader("Content-Type", equalTo("application/xml"))
.withRequestBody(containing("<b:Name>Test</b:Name>"))
.withRequestBody(matchingXPath("//Age/text()",equalTo("18")))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/xml")
.withBody("Passed")));
Result:
Request was not matched
=======================
-----------------------------------------------------------------------------------------------------------------------
| Closest stub | Request |
-----------------------------------------------------------------------------------------------------------------------
|
GET | GET
/vi/test.svc | /v1/test.svc
|
Content-Type: application/xml | Content-Type: application/xml
|
//Age/text() | <test xmlns="http://abc.example.com">
<request <<<<< Body does not match
| xmlns:b="http://abc.example.com/b"
| xmlns:i="http://abc.example.com/i">
<b:Name>Test</b:Name>
<b:Age>18</b:Age>
<b:Count>2020</b:Count>
</request>
</test>
|
-----------------------------------------------------------------------------------------------------------------------
Can anyone tell me how to check value for this?
Age element is under the http://abc.example.com/b namespace URI. From Wiremock documentation you can declare the in scope namespace for your XPath expression like this:
.withRequestBody(matchingXPath("//b:Age[.=18]")
.withXPathNamespace("b", "http://abc.example.com/b"))
Related
Below scenario bringing in me proper SOAP body but I'm not able to extract it's values using xpath expression
The path expression /*/soap:Body/m:NumberToDollarsResponse/m:NumberToDollarsResult/text() I have formed using this website
https://codebeautify.org/Xpath-Tester
val httpConf = http.baseUrl("https://www.dataaccess.com")
val headerXml = Map("Keep-Alive" -> "115", "Content-Type" -> "application/soap+xml; charset=utf-8")
val soapXmlScn = scenario("make First Soap Call")
.exec(
http("Soap API Call With XML")
.post("/webservicesserver/numberconversion.wso")
.headers(headerXml)
.body(StringBody("""<?xml version="1.0" encoding="utf-8"?>
<soap20:Envelope xmlns:soap20="http://www.w3.org/2003/05/soap-envelope">
<soap20:Body>
<NumberToDollars xmlns="http://www.dataaccess.com/webservicesserver/">
<dNum>45</dNum>
</NumberToDollars>
</soap20:Body>
</soap20:Envelope>"""))
.check(status.is(200))
.check(xpath("""//*/soap:Body/m:NumberToDollarsResponse/m:NumberToDollarsResult/text()""").saveAs("doller_value" ))
)
.exec {
session =>
println("doller value >>>> " + session("doller_value").as[String].toString)
session
}
Response body is
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<m:NumberToDollarsResponse xmlns:m="http://www.dataaccess.com/webservicesserver/">
<m:NumberToDollarsResult>forty five dollars</m:NumberToDollarsResult>
</m:NumberToDollarsResponse>
</soap:Body>
</soap:Envelope>
The error shown on console is
12:22:16.880 [ERROR] i.g.c.a.b.SessionHookBuilder$$anon$1 - 'hook-1' crashed with 'j.u.NoSuchElementException: No attribute named 'doller_value' is defined', forwarding to the next one
namespace List needs to be provided to your xpath check as below and my request working fine. Those namespace URLs are mentioned in your SOAP response xml only
.check(xpath("""//soap:Envelope/soap:Body/m:NumberToDollarsResponse/m:NumberToDollarsResult/text()""", List("soap" -> "http://www.w3.org/2003/05/soap-envelope", "m" -> "http://www.dataaccess.com/webservicesserver/")).findAll.saveAs("doller_value" ))
Using Karate, I would like to build a soap request.
There are Optional elements in the SOAP Request, how to remove them based on the Scenario Outline: Example?
Shared an example, for the purpose of discussion. If there is already a sample code, please share, thank you.
Feature: SOAP request to get Customer Details
Background:
Given url 'http://localhost:8080/CustomerService_V2_Ws'
Scenario Outline:
* def removeElement =
"""
function(parameters, inputXml) {
if (parameters.city = null)
karate.remove(inputXml, '/Envelope/Header/AutHeader/ClientContext/city');
if (parameters.zipcode = null)
karate.remove(inputXml, '/Envelope/Header/AutHeader/ClientContext/zipcode');
return inputXml;
}
"""
* def inputXml = read('soap-request.xml')
* def updatedXml = removeElement(parameters,inputXml)
Given request updatedXml
When soap action ''
Then status <http_code>
Examples:
| CustomerId | ZipCode | City |
| 001 | null | null |
| 002 | 41235 | null |
| 003 | null | New York |
**Contents of "soap-request.xml"**
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsc1:AutHeader xmlns:wsc1="http://example.com/ws/WSCommon_v22">
<wsc1:SourceApplication>ABC</wsc1:SourceApplication>
<wsc1:DestinationApplication>SoapUI</wsc1:DestinationApplication>
<wsc1:Function>CustomerService.readDetails</wsc1:Function>
<wsc1:Version>2</wsc1:Version>
<wsc1:ClientContext>
<wsc1:customerid>10000</wsc1:customerid>
<!--Optional:-->
<wsc1:zipcode>11111</wsc1:zipcode>
<!--Optional:-->
<wsc1:city>xyz</wsc1:city>
</wsc1:ClientContext>
</wsc1:AutHeader>
</soapenv:Header>
<soapenv:Body />
</soapenv:Envelope>
Yes my suggestion is use embedded expressions. When the expression is prefixed with 2 hash signs, this will "delete if null" which was designed for your exact use case. Here is an example:
Scenario: set / remove xml chunks using embedded expressions
* def phone = '123456'
# this will remove the <acc:phoneNumberSearchOption> element
* def searchOption = null
* def search =
"""
<acc:getAccountByPhoneNumber>
<acc:phoneNumber>#(phone)</acc:phoneNumber>
<acc:phoneNumberSearchOption>##(searchOption)</acc:phoneNumberSearchOption>
</acc:getAccountByPhoneNumber>
"""
* match search ==
"""
<acc:getAccountByPhoneNumber>
<acc:phoneNumber>123456</acc:phoneNumber>
</acc:getAccountByPhoneNumber>
"""
Do note that there are many more examples here: xml.feature
I'm trying to request a line from Azure Table Storage using the REST API and C++, but always got the following error:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<cod_e>JsonFormatNotSupported</cod_e>
<message xml:lang="en-US">JSON format is not supported.
RequestId:0ccb3b9b-0002-0029-3389-0d2fa1000000
Time:2016-09-13T06:39:13.3155742Z</message>
</error>
Here is my request:
GET https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>')?<sharedsignature>
Here how I fill request headers, as from https://msdn.microsoft.com/en-us/library/dd179428.aspx:
std::string sharedAccessSignature("<sharedsignature>");
std::string dateTime(GetDateTime());
std::string stringToSign(dateTime + "\n/" + account + "/" + "<mytable>");
std::string request("(PartitionKey='<mypartition>',RowKey='<myrow>')");
stringToSign += request;
std::string signatureString(HMACSHA256(stringToSign, sharedAccessSignature));
headers["Authorization"] = "SharedKeyLite " + account + ":" + signatureString;
headers["DataServiceVersion"] = "3.0;NetFx";
headers["MaxDataServiceVersion"] = "3.0;NetFx";
headers["x-ms-version"] = "2015-12-11";
headers["x-ms-date"] = dateTime;
headers["Accept"] = "application/json;odata=verbose";
headers["Accept-Charset"] = "UTF-8";
The table exists and is not empty.
Please advise what's wrong?
Update 1
Removing sharedsignature from request, i.e. GET https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>') leads to the same result.
Removing Authorization header from the request leads to the same result too.
Update 2
Putting https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>')?<sharedsignature> in a browser produces a valid response, but in Atom format.
<?xml version="1.0" encoding="utf-8"?>
<entry
xml:base="https://<myaccount>.table.core.windows.net/"
xmlns="http://www.w3.org/2005/Atom"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
m:etag="W/"datetime'2016-09-13T05%3A29%3A51.211538Z'"">
<id>https://<myaccount>.table.core.windows.net/<mytable> (PartitionKey='<mypartition>',RowKey='<myrow>')</id>
<category term="<myaccount>.<mytable>" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="<mytable>" href="<mytable> (PartitionKey='<mypartition>',RowKey='<myrow>')" />
<title />
<updated>2016-09-13T11:25:19Z</updated>
<author><name /></author>
<content type="application/xml">
<m:properties>
<d:PartitionKey><mypartition></d:PartitionKey>
<d:RowKey><myrow></d:RowKey>
<d:Timestamp m:type="Edm.DateTime">2016-09-13T05:29:51.211538Z</d:Timestamp>
<d:Score m:type="Edm.Int32">1050</d:Score>
</m:properties>
</content>
</entry>
Update 3
Investigation situation using curl I found that adding Accept: application/json;odata=fullmetadata to the request headers leads to the error above. Default Accept */* in headers produces valid Atom response.
Finally, got it!
The issue was in my shared signature.
While looking at it I found sv=2012-02-12 part, and assumed, that it means API version. The version, before JSON support was introduced! I created a new shared signature and finally got JSON with the following curl command.
curl -v -H "Accept: application/json;odata=nometadata" -H "x-ms-version: 2015-12-11" "https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>')?<mysharedsignature>"
So, for everyone, who face the same issue in the future: please check your signature first!
Is it possible to pass a parameter through URL in perl catalyst
I have a link
<a href="/vbo/mortgage_reduction/yearly" >Yearly </a>
Can I pass a parameter with the link, like
<a href="/vbo/mortgage_reduction/yearly/1" >Yearly</a>
if so, how can I take the value in the module ?
I have just started learning Catalyst myself, but I can say that seems to be what :Args is for. You specify the number of parameters you need and they are added to #_. I have made this test:
sub test :Local :Args(1) {
my ( $self, $c, $word ) = #_;
$c->response->body($word);
}
and loaded http://localhost:3000/test/hello. This displayed "hello" in the browser and the server output:
[info] *** Request 1 (0.083/s) [14444] [Thu Jun 5 11:29:18 2014] ***
[debug] Path is "test"
[debug] Arguments are "hello"
[debug] "GET" request for "test/hello" from "127.0.0.1"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Length: unknown
[info] Request took 0.00722s (138.504/s)
.------------------------------------------------------------+-----------.
| Action | Time |
+------------------------------------------------------------+-----------+
| /test | 0.000194s |
| /end | 0.000265s |
'------------------------------------------------------------+-----------'
This is documented in Catalyst::Manual::Intro under Action types.
It is also possible for a series of controller methods to examine the same request, each taking a certain number of those "URL parameters", with :CaptureArgs and action chains.
I want to make a post request in Scala to this API http://api.atinternet-solutions.com/toolbox/reporting.asmx
I first did it with a curl like this :
curl -X POST -T post.txt -H "Content-Type: application/soap+xml; charset=utf-8" http://api.atinternet-solutions.com/toolbox/reporting.asmx -v
and I got what I expected.
Now I want to call the API programatically with a simple HttpClient
val httpClient = new DefaultHttpClient()
def postRequest=new HttpPost("https://api.atinternet-solutions.com/toolbox/reporting.asmx")
postRequest.addHeader("Content-Type","application/soap+xml ; charset=utf-8")
postRequest.addHeader("SOAPAction","\"http://www.xiti.com/queryReport\"")
val file=new File("post.txt")
val fe=new FileEntity(file,"application/soap+xml;charset=utf-8")
postRequest.setEntity(fe)
val httpResponse=httpClient.execute(postRequest)
println(httpResponse.getStatusLine.toString)
val rspStr=Source.createBufferedSource(httpResponse.getEntity.getContent).mkString
println(rspStr)
but I get an HTTP/1.1 500 Internal Server Error
and printing the rspStr yields
"?xml version="1.0" encoding="utf-8"?><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:Receiver</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">Server was unable to process request. ---> Root element is missing.</soap:Text></soap:Reason><soap:Detail /></soap:Fault></soap:Body></soap:Envelope"
The post.txt looks like below, except I set the good information instead.
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<NXHeader xmlns="http://www.xiti.com/">
<GUID>string</GUID>
<SecurityKey>string</SecurityKey>
<Site>int</Site>
</NXHeader>
</soap12:Header>
<soap12:Body>
<queryReport xmlns="http://www.xiti.com/">
<startDate>int</startDate>
<endDate>int</endDate>
<query>string</query>
<param>string</param>
<typereport>XML or CSV</typereport>
</queryReport>
</soap12:Body>
</soap12:Envelope>
The curl action which is working is done from my scala project directory. I printed post.txt in scala and got the good content.
I cannot figure out what is going wrong. Thank you for your help
I tried your call with the dispatch library.
This is my code
import dispatch._
import java.io.File
object ToolBox {
val endpoint = url("https://api.atinternet-solutions.com/toolbox/reporting.asmx").POST
.addHeader("Content-Type","application/soap+xml ; charset=utf-8")
.addHeader("SOAPAction",""" "http://www.xiti.com/queryReport" """)
def report = Http( endpoint <<< new File("post.txt") > as.xml.Elem)
def tryReport = {
val res = report.either
for {
ex <- res.left
} yield "Something got wrong " + ex.getMessage
}
}
The service replies with a status 500 like you, but the faultString in the response xml is: A parameter is missing in your NXHeader or you have a namespace issue.
Is it what you would expect, since the post.txt body contains only the placeholders from the query report example, instead of real parameters?
I found what was going wrong.
Replace
def postRequest
by
val postRequest.
Tks again