AWS API Gateway VTL Include Source API JSON in Response Template - json

We would like to include the Integration/Source API JSON in the response, but when we attempt to include the Object, it does not encode properly.
"success": true,
"message": "Resource Call Made Successfully",
"data": {ip=127.0.0.1, ipv4=127.0.0.1, ipv6=0:0:0:0:0:0:0:0, asn=null, asn_name=null, country=US, useragent={family=Other...
As you can see, the strings lose their quotes; breaking the JSON. Here's the template;
#set($inputRoot = $input.path("$"))
{
"success": true,
"message": "Resource Call Made Successfully",
"data": $inputRoot
}
I've tried using $json.parse(), escaping, etc with no luck. Anyone familiar enough to give some direction on how to stringify this so I can include it in the response?

Use syntax like below,
"subject": "$util.escapeJavaScript($input.path('$.Attributes.subject.S')).replaceAll(\"\\\\'\",\"'\")"
It's an explanation in $util.escapeJavaScript() function

Related

Cypress intercept API JSON response and extract URL

My web app sends an API POST request to create an application and returns JSON response. I want to access one particular JSON object from that response.
My JSON starts like this
[
{
"status_code": 201,
"body": {
"created": "2021-01-28T00:00:00Z",
"modified": "2021-01-28T00:00:00Z",
"id": "a2d86d17-9b3c-4c4d-ac49-5b9d8f6d6f8f",
"applicant": {
"id": "07f1e1d3-0521-401b-813e-3f777f2673c6",
"status": "Pending",
"first_name": "",
"last_name": "",
"URL": "some onboarding url"
And I wanna take that URL in the JSON response and visit it later in my cypress automation script.
Notice that the JSON repsonse starts with a square bracket not a curly bracket, which means, the whole response is an object, I assume?
My cypress script looks like this
cy.contains('button', 'CONTINUE').click()
cy.EmailGen('candidate').then(email => {
cy.get('#emails\\[0\\]').type(`${email}`)
cy.wrap(email).as('candidateEmail')
})
//writing intercept here, before the Send application button, which triggers the POST req.
cy.intercept('/hr/v1/applications/invite').as('getURL')
cy.get('button').contains('SEND APPLICATION').click({ force: true })
//waiting on the alias of intercept and using interception to print objects from response
cy.wait('#getURL').then((interception)=> {
cy.log(interception.response.body.applicant.URL)
})
cy.Logout()
The script executes with no errors. Just that nothing is logged in the cy.log statement. Below is the screen.
I also tried using another method as given below.
cy.intercept('/hr/v1/applications/invite',(req) => {
req.reply((res=> {
expect(res.status_code).to.equal('201')
expect(res.body.applicant.status).to.equal('Pending')
}))
})
In this case, I get a assert error embedded with the request and response along with some other stuff which I am unable to understand.
The complete error goes something like this...
"expected The following error originated from your test code, not from Cypress.\n\n > A response callback passed to req.reply() threw an error while intercepting a response:\n\nexpected undefined to equal '201'\n\nRoute: {\n "matchUrlAgainstPath": true,\n "url": "/hr/v1/applications/invite"\n}\n\nIntercepted request:{} Intercepted response: {} When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. to include window.zE is not a function"
Its a bit weird to read this..
My application sometimes throws this exception, which I have handled using following code.
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('window.zE is not a function')
done()
return false
})
I really hope I have explained everything here. Please, help a noob.
Regards
As Richard Matsen suggested in the comments,
I used console.log(interception.response) and checked the console output in the browser controlled by Cypress.
I Noticed that the response json structure was something different than what I got in the network tab of developers tools, while using the web app.
The response was something like below...
{headers: {…}, url: "https://example.com/hr/v1/applications/invite/batch/", method: null, httpVersion: "1.1", statusCode: 200, …}
body: Array(1)
0:
body:
applicant: {id: "c6b2d686-d4f3-483e-abc8-e4641c365845", status: "Pending", first_name: "", last_name: "", email: "qa2+candidate879#example.com", …}
applicant_status: "NONE"
applicant_status_label: "None"
created: "2021-01-29T00:00:00Z"
get_applicant_status_display: "None"
id: "ad2939f5-c8ab-490a-a9e1-b0474de69e2c"
URL: "some url"
This made me modify the json traverse to
interception.response.body[0].body.applicant.URL
If others have a neat way to handle this, please let me know!

How do I access a json property nested in the ['error'] property of another json reponse?

I'm requesting a list of possible stock ticker symbols from the Yahoo Stock Lookup API, I used the CORS Anywhere service to avoid problems. Unfortunately the original json response from the Yahoo API gets formatted as 'text' in the CORS anywhere 'error' property.
I used this previously asked question as a reference on how to access nested properties.
this is what the json reponse looks like:
{
"headers": {
"normalizedNames": {},
"lazyUpdate": null
},
"status": 200,
"statusText": "OK",
"url": "https://cors-anywhere.herokuapp.com/http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=Amd&region=1&lang=en&callback=YAHOO.Finance.SymbolSuggest.ssCallback",
"ok": false,
"name": "HttpErrorResponse",
"message": "Http failure during parsing for https://cors-anywhere.herokuapp.com/http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=Amd&region=1&lang=en&callback=YAHOO.Finance.SymbolSuggest.ssCallback",
"error": {
"error": {
"line": 9848,
"column": 56,
"sourceURL": "capacitor://localhost/vendor-es2015.js"
},
"text": "YAHOO.Finance.SymbolSuggest.ssCallback({\"ResultSet\":{\"Query\":\"Amd\",\"Result\":[{\"symbol\":\"AMD\",\"name\":\"Advanced Micro Devices, Inc.\",\"exch\":\"NMS\",\"type\":\"S\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Equity\"},{\"symbol\":\"DOX\",\"name\":\"Amdocs Limited\",\"exch\":\"NMS\",\"type\":\"S\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Equity\"},{\"symbol\":\"AMDVX\",\"name\":\"American Century Mid Cap Value Fund R6 Class\",\"exch\":\"NAS\",\"type\":\"M\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Fund\"},{\"symbol\":\"AMDWX\",\"name\":\"Amana Mutual Funds Trust Developing World Fund Investor\",\"exch\":\"NAS\",\"type\":\"M\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Fund\"},{\"symbol\":\"AMDAX\",\"name\":\"AMIDEX35 Israel Fund Class A\",\"exch\":\"NAS\",\"type\":\"M\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Fund\"},{\"symbol\":\"AMDEX\",\"name\":\"AMIDEX35 Israel Mutual Fund\",\"exch\":\"NAS\",\"type\":\"M\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Fund\"},{\"symbol\":\"AMDCX\",\"name\":\"AMIDEX35 Israel Fund Class C\",\"exch\":\"NAS\",\"type\":\"M\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Fund\"},{\"symbol\":\"AMDRX\",\"name\":\"American Beacon Mid-Cap Value Fund R6 Class\",\"exch\":\"NAS\",\"type\":\"M\",\"exchDisp\":\"NASDAQ\",\"typeDisp\":\"Fund\"},{\"symbol\":\"AMDLY\",\"name\":\"Amada Holdings Co., Ltd.\",\"exch\":\"PNK\",\"type\":\"S\",\"exchDisp\":\"OTC Markets\",\"typeDisp\":\"Equity\"}]}});"
}
}
This is what I tried:
return this.yahooResult.subscribe(data => {return data['error']['text']['ResultSet']['Result']['symbol']});
I'm trying to access "symbol" : "AMD" from the Yahoo API response that is nested in the "text" property of the CORS repsonse.
I don't get much information from the error:
⚡️ [error] - ERROR
You don't have json there, you have a javascript snippet:
YAHOO.Finance.SymbolSuggest.ssCallback()
With some escaped text passed into it.
It's not a case of parsing this, its a case of fixing the error.
I think you are using the wrong API call. It has a callback parameter in it which is wrapping the reply in a function and breaking cors-anywhere's ability to parse the response.
The url you should be using is:
http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=Amd&region=1&lang=en
Not:
http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=Amd&region=1&lang=en&callback=YAHOO.Finance.SymbolSuggest.ssCallback
Then just plain JSON gets returned and cors-anywhere should be able to parse it.

How to parse dynamic json reponse and get specific value and pass it as an input to next request

I get .json file as a response from an API and from that file I should parse and fins specific parameter and pass it as an input to the next request, how do I do that using Katalon.
If I say
response = JSON.parse("response.json");
it says it is unable to identify JSON as valid. Can someone help me out with the solution?
Your JSON is invalid, maybe it is a copy-paste issue.
The valid JSON should be
{
"responseStatusCode": "OK",
"data": {
"screenName": "employeeTimeslip",
"screenType": "Redirect",
"searchResultCount": 0,
"rows": [],
"tabs": [],
"searchParams": {
"employeeID": "000092926",
"timeslipNumber": "201900019701"
}
}
}
So, you were missing a "," between "OK" and "data" and two closing curly braces at the end of the file.
You can check JSON files for validity yourself using online JSON validators, for example, this one.
i found a way to read specific parameter from the json response file like below:
val scn = scenario("ClaimSubmission")
.exec(http("request_2")
.post("URL")
.headers(headers_2)
.body(RawFileBody("json file path"))
.check(jsonPath("$..timeslipnumber").find.saveAs("timeslipnumber")))
Timeslip number would be retrieved using : .check(jsonPath("$..timeslipnumber").find.saveAs("timeslipnumber")))

AWS API Gateway Mapping Template JSON

I've got a API stage that's NOT using "Lambda Proxy integration" which has a Lambda function passing an error.
In the mapping template I have this:
$input.path("$.errorMessage")
Which results in the output of this:
{
"headers": {
"apiVersion": "20190218.1",
"isTesting": true
},
"body": {
"statusCode": 503,
"status": "Service Unavailable",
"title": "One or more of our data providers are currently offline for scheduled maintenance"
}
}
The header values are mapped to template headers and pull through correctly, however I need the body to transform to this:
{
"statusCode": 503,
"status": "Service Unavailable",
"title": "One or more of our data providers are currently offline for scheduled maintenance"
}
Whatever I have tried, body always returns as a blank string, an empty body, or an invalid JSON.
This is the closest I've got but it returns an invalid JSON:
$util.parseJson($input.path("$.errorMessage")).body
Result (comes back with no quotes):
{statusCode=503, status=Service Unavailable, title=One or more of our data providers are currently offline for scheduled maintenance}
Is it possible to do what I'm after? I can't find a reverse for $util.parseJson (i.e, stringify).
Thanks!
I think the original poster has probably moved on in the past 11 months, but in case anyone else stumbles across this question, $input.json('$.errorMessage.body') should work.

JSON API result format

Folks,
Designing my first API in Node.JS using restify.js. My background is not webapis, pardon my amateur questions. In any case, I would like to have the res.send(data); responses to comply with the http://jsonapi.org/format/ so that my mobile application can start utilizing the api calls. At the moment if you were to call my api, it would return data in the following format:
{"Count":1,"Items":[{"dbsource":{"S":"foo"},"id":{"S":"5002820"},"name":{"S":"fnameblah,lnameblah"},"expiration":{"S":"06/13/2015"},"type":{"S":"bar"}}]}
Actually what you see above is just a return of a DynamoDB Query call.
So the question is... do you use a special library that you can pass data to, which would format and return the data in JSON format. Which in turn you can return it via res.send(data) to the clients, or is it up to us to make 'data' JSON compliant, then return it? At the end of the day we all want the results to look like:
{
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "9",
"comments": [ "5", "12", "17", "20" ]
}
}]
}
Thanks!
In server side, stringify JSON object,
//...
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(data)); //data is JSON object
res.end();
In client side, parse JSON string accordingly.
EDIT: Corrected response content type.
JSON data from server should be a JSON string
You have to parse it back the JSON format in client.
JSON.parse(string); // return JSON object