Parsing JSON response using Citrus framework for URLEncode - parsing

I'm using Citrus to automate our RESTful services where service1's input param is passed onto service2' input after URLEncoding.
Below is the code snippet, to explain the ways I tried but somehow unable to URLEncode, on top of designer.traceVariables().
Owing to the limitation (possible known!) that the response params can't be passed outside of context, I had to call multiple send(), receive() calls, defined in the same Gherkin method as below.
I'm able to print the variable myVar (extracted from payLoad) using designer.traceVariables() but unable to process & persist it for further use, to pass onto the next service call.
#When("^I call CPAuth service for ChasePay$")
public void i_call_CPAuth_service_for_ChasePay() throws Throwable {
designer.send("CitrusContext")
.messageType(MessageType.JSON)
.header(X_JPMC_CSRF_TOKEN_HEADER, csrfToken)
.header(HTTP.CONTENT_TYPE, APPLICATION_JSON)
.header(COOKIE, ConnRoutePNames.DEFAULT_PROXY + "=" + proxy)
.header("citrus_endpoint_uri", authUrl +"/auth/fcc/login")
.message(new HttpMessage("<large_string=no_issues_here>").method(HttpMethod.POST));
designer.receive("CitrusContext").messageType(MessageType.JSON)
.validate("$.response", "secauth")
.validate("$.newstoken", false)
.validate("$.smtoken", "void")
.extractFromPayload("$.spid", "myVar");
String request = URLEncoder.encode("appStoreBundleId=com.testmerchant.sampleapp&version=APP%2BBUILD%2BVERSION&channelId=MPD&spid=**${myVar}**&type=json&chasePayMerchantId=1390xxx", CharEncoding.UTF_8);
System.out.println("request: "+request);
designer.send("CitrusContext")
.messageType(MessageType.JSON)
.header(X_JPMC_CSRF_TOKEN_HEADER, csrfToken)
.header(HTTP.CONTENT_TYPE, APPLICATION_JSON)
.header(COOKIE, ConnRoutePNames.DEFAULT_PROXY + "=" + proxy)
.header("citrus_endpoint_uri", hostUrl +"/pwc/provisioning/pos/otp/contact/v20160313/list.action")
.message(new HttpMessage(request).method(HttpMethod.POST));
Result:
Before encoding: MSZp2V/czcKsxej+Q04Da/QeVlo=MCwCFAqrBN/6/J8WZENecE7JQlEODnecAhQCcnXGBjMoiQ7deunlyXKacFo/lQ== (This should be the string, to be encoded.)
After encoding: %3D%24%7BmyVar%7D%26
Any help would be greatly appreciated, Thanks.

The encode operation destroys the "${myVar}" expression before Citrus is able to parse and interpret the expression as part of the message payload. You need to execute the encode operation as a Citrus function. How to write this function is described here: http://citrusframework.org/docs/custom-functions/
You end up having something like:
designer.send("CitrusContext")
.messageType(MessageType.JSON)
.message(new HttpMessage("custom:urlEncode('appStoreBundleId=com.testmerchant.sampleapp&version=APP%2BBUILD%2BVERSION&channelId=MPD&spid=**${myVar}**&type=json&chasePayMerchantId=1390xxx')").method(HttpMethod.POST));

Related

Access session value in gatling checks

I use gatling to send data to an ActiveMQ. The payload is generated in a separate method. The response should also be validated. However, how can I access the session data within the checks
check(bodyString.is()) or simpleCheck(...)? I have also thought about storing the current payload in a separate global variable, but I don't know if this is the right approach. My code's setup looks like this at the moment:
val scn = scenario("Example ActiveMQ Scenario")
.exec(jms("Test").requestReply
.queue(...)
.textMessage{ session => val message = createPayload(); session.set("payload", payload); message}
.check(simpleCheck{message => customCheck(message, ?????? )})) //access stored payload value, alternative: check(bodystring.is(?????)
def customCheck(m: Message, string: String) = {
// check logic goes here
}
Disclaimer: providing example in Java as you don't seem to be a Scala developper, so Java would be a better fit for you (supported since Gatling 3.7).
The way you want to do things can't possibly work.
.textMessage(session -> {
String message = createPayload();
session.set("payload", payload);
return message;
}
)
As explained in the documentation, Session is immutable, so in a function that's supposed to return the payload, you can't also return a new Session.
What you would have to do it first store the payload in the session, then fetch it:
.exec(session -> session.set("payload", createPayload()))
...
.textMessage("#{payload}")
Regarding writing your check, simpleCheck doesn't have access to the Session. You have to use check(bodyString.is()) and pass a function to is, again as explained in the documentation.

Twitter API v2 Streaming with Retrofit or OkHttp

I am trying integrate the new Twitter API specifically the streaming tweets part in my android app, I am using Retrofit for my http calls.
When I try to make the call to get the streaming tweets it just hangs and does not return anything.
this is my retrofit call
#Streaming
#GET("tweets/search/stream")
suspend fun getFilteredStream(#Header("Authorization") token:String)
I then tried making a call with just OkHttp as shown in the documentation I get a successful response but I dont know how to stream the data.
I can make the call successfully via a curl call and see the data no problem.
How do I stream the data via retrofit or OkHttp
Update:
With OkHttp I was able to get data by doing this
val client: OkHttpClient = OkHttpClient().newBuilder()
.build()
val request: Request = Request.Builder()
.url("https://api.twitter.com/2/tweets/search/stream")
.method("GET", null)
.build()
val response: Response = client.newCall(request).execute()
val source = response.body?.source()
val buffer = Buffer()
while(!source!!.exhausted()){
response.body?.source()?.read(buffer, 8192)
val data = buffer.readString(Charset.defaultCharset())
}
data holds the string data representation of multiple tweet objects but how do I read one tweet at a time, or parse the response like this?
From the docs, I think you'll need to combine the two examples you have.
https://github.com/square/retrofit/blob/108fe23964b986107aed352ba467cd2007d15208/retrofit/src/main/java/retrofit2/http/Streaming.java
Treat the response body on methods returning {#link ResponseBody ResponseBody} as is, i.e. without converting the body to {#code byte[]}.
And example calling code
https://github.com/square/retrofit/blob/108fe23964b986107aed352ba467cd2007d15208/retrofit/src/test/java/retrofit2/CallTest.java#L599
I suspect, dependending on the JSON API you use you may be able to use a Streaming API from the response body. But if not you could split on either just newline or newline followed by { on next line and parse individually. Sorry I can't help here.
See https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON

http url parameter Invalid Character Error

I have developed a REST API using feathers.js (https://feathersjs.com/).
When trying to do a HTTP 'read' request in Flutter using package:http/http.dart I have encountered an error. The http.dart library is unable to correctly parse the query params I pass to the URI.
The error I receive through the Android Studio debug console is ;
FormatException: Invalid character (at character 84) E/flutter
(11338): ...lk.com/weatherobs?last=true&location[$in]=Bellambi&location[$in]=Nowra ....
The error is indicating the square brackets and possibly the $ sign ('[$in]' ) are the issue.
_getDemoRequest() {
String url = r"http://demoapi.ap-southeast-2.elasticbeanstalk.com/weatherobs?last=true&location[$in]=Bellambi&location[$in]=Nowra&location[$in]=Sydney Airport&location[$in]=Thredbo Top Station&location[$in]=Hobart&location[$in]=Coolangatta";
http.read(url).then(print);
}
In the URL I have tried prefixing the String with and without 'r' for a raw string to no avail.
I have also tried using httpClient with params with no success and the exact same error on the square brackets eg '[$in]'
String httpbaseUri = "http://xxxx.ap-southeast-2.elasticbeanstalk.com";
String qParams = r"?last=true&location[$in]=Bellambi&location[$in]=Nowra";
String path = "/weatherobs";
var _uri = new Uri.http(baseUri, path, qParams);
await httpClient.read(_uri, headers: {"Accept": "application/json"});
As a person with approximately 3 weeks of Flutter/Dart experience I believe its an elementary problem, but one in which several hours of research has uncovered no solution.
The ways the URI query parameters are structured (with the square brackets ie [$in]) are dictated by the feathers.js framework.
Any help would be appreciated.
It has been brought to my attention in another thread https://stackoverflow.com/questions/40568/are-square-brackets-permitted-in-urls :
That the URL Specification RFC 3986 generally does not permit square brackets in an URL.
My question was triggered as the get request works as intended in Postman, Chrome Browser and also javascript applications using axios.js, but not in an application developed in Flutter/Dart using standard http.read methods.
It doesn't look like [] are supported in the URL (except for the host IP for IPv6). See Are square brackets permitted in URLs?.
Please check if the API accepts them when they are encoded like:
void main() {
var url = r'http://demoapi.ap-southeast-2.elasticbeanstalk.com/weatherobs';
var locationKey = Uri.encodeQueryComponent(r'location[$in]');
var qParams = 'last=true&$locationKey=Bellambi&$locationKey=Nowra&$locationKey=Sydney Airport&$locationKey=Thredbo Top Station&$locationKey=Hobart&$locationKey=Coolangatta';
try {
print(Uri.parse(url).replace(query: qParams));
} catch(e) {
print(e);
}
}
DartPad example
See also api.dartlang.org/stable/1.24.3/dart-core/Uri/…
You can use this flutter package which allow you to communicate with your feathers js server from flutter app as said in: https://stackoverflow.com/a/65538226/12461921

routing help in Txroutes library

I need to route the following to a function :
http://www.example.com/docs/?key1=value1&key2=value2
And the route code for it is
dispatcher.connect(name='xyz', route='/docs/{item}', controller=c, action='docs')
so, can you help me with the “route” part as in what should come there so for an incoming request the action gets called.
As in how to relate route='/docs/{item}' and /docs/?key1=value1&key2=value2
HTTP GET request (/docs/) followed by a query string (?key1=value1&key2=value2). You'd use Twisted's normal facilities for accessing the query string.
def docs(self, request):
return '<html><body>Got %s args</body></html>' % request.args
to retrieve from the array use request.args['key1'][0] to get 'value1'.

JSON API request app (rails), rendering results

I need to develop a small Rails app that makes a request to an JSON API, introducing the parameters into an initial form, check if we get a real response and then render the results into a view (html.erb).
Do you know where can I get good material to do these steps? Any help is welcome.
I'm reading some near example:
params_string = "whatever"
params_string_with_api_key = params_string + "&" + ##API_KEY
hashkey = Digest::SHA1.hexdigest(params_string_with_api_key)
params_string += "&hashkey=#{hashkey}"
res = Net::HTTP.get_response("api.somecompany.com", "/some/url.json?#{params_string}")
res_sha1 = Digest::SHA1.hexdigest(res.body + ##API_KEY)
#verified = res["X-Somecompany-Response-Signature"] == res_sha1
parsed_json = ActiveSupport::JSON.decode(res.body)
#results = parsed_json["results"]
Is it always needed to encode the parameters string when you do the Net::HTPP request? Is there another way?
What does exactly params_string += "&hashkey=#{hashkey}"?
Thank you!
What does exactly params_string += "&hashkey=#{hashkey}"?
params_string is a string that looks like ?param1=val&param2=val2.... Your last piece of code is just appending another param to the string. If your issue is with the #{} fragment, this syntax, in a ruby double-quoted string, allows you to use the value of a var.
Is it always needed to encode the parameters string when you do the Net::HTPP request? Is there another way?
I don't see the parameters string being encoded here. All I see is a checking of the results, done by comparing a response header with a SHA1'd response body.
Not really related to your questions : I went away from Net::HTTP a while back, having troubles with segfault. I now use Typhoeus for all requests through the network.

Resources