axios.post() error about circular structure - node.js

Please guide me in case I'm not in proper use of axios. This simple piece of code can directly run:
const axios = require('axios')
axios.post('https://exp.host/--/api/v2/push/send', {"to":["ExponentPushToken[xxxxxxx]"],"title":"test title","body":"test body."})
.then(responseExpo => {
console.log("expo replied normally: " + JSON.stringify(responseExpo));
})
.catch(error => {
console.log("expo replied with error: " + JSON.stringify(error,null,4));
});
The result is:
Promise { <pending> }
expo replied with error: {}
"axios": "^0.19.2"
I tried to post with api tools and see a response with normal 200 status code:
{
"data":[
{
"status": "error",
"message": "\"ExponentPushToken[xxxxxxx]\" is not a registered push notification recipient",
"details":{
"error": "DeviceNotRegistered"
}
}
]
}
(you may ignore the "error": "DeviceNotRegistered" inside this json cos it's expected because I have put an invalid xxxxx input value when calling the api. Even putting a valid input value the result is still returning to the catch block with empty error)
I'm expecting it to return to the then block cos the server actually response with 200 with well formatted json result.
Have I done something wrong so that the call returns to the catch block? Cos the error is empty I have no idea what went wrong.
===============================
after jfriend's reminder I changed to directly disply the error.
console.log("expo replied with error: " + error);
it is show like this now:
Promise { <pending> }
expo replied with error: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'ClientRequest'
| property 'socket' -> object with constructor 'TLSSocket'
--- property '_httpMessage' closes the circle
Anyone can let me know what exactly it means and guide me how to correct my usage?

(problem resolved). the response (responseExpo in the question) is neither a plain data JSON nor a plain string. it is an object with (see github.com/axios/axios#response-schema) some attributes. The real response content is inside "response.data". I was wrongly treating the response to be a plain json object or the http response content.

I had a similar problem and as solution, I used HttpService from nestjs which returns Observable<AxiosResponse<T>>. I fixed the problem by piping and plucking the request like this:
http.put<T>(url, data, config).pipe(pluck('data'))

I had a similar problem with HttpService from nestjs which returns Observable<AxiosResponse<any>>. I resolve with:
this.httpService.post(this.legacyAccessTokenEndpoint, form, { headers: form.getHeaders() }).pipe(map(x => x?.data))

Related

Why is node.js fetch giving a 'Bad Request' error?

I am getting a 400 error (bad request) from this POST:
siteData.myPost = async function (url, data) {
let options = {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(data)
}
try {
const response = await fetch(quilkinUrlBase() + url,options);
return response.json();
}
catch (error) {
qPopup.Alert("Error with web request: " + error);
}
};
(the fetch address computes to "http://localhost:1337/UpdateSiteVisits").
This can't, of course, convert 'response' to json because the response is a DOC containing the 400 error message.
in server.js I have the following callback definition for the URL specified in the fetch:
app.post("/UpdateSiteVisits", sites.updateVisits);
in the debugger, the code never reaches updateVisits().
I have a very similar construct with a GET:
app.get("/GetSitesForType/:type", sites.findByType);
which works fine, so I assume the problem is with the 'options' object (which the GET doesn't use). In the POST case the data is just an integer ID, and if I change the data format to plain text (instead of json), the post works fine.
If leave the format as json, and send an object, rather than a simple integer, the post also works fine. So it looks like the system just doesn't like converting a single integer to json.
I needed to send the integer as json, so instead of using the method like this:
siteData.myPost("UpdateSiteVisits", siteID)
I needed to use
siteData.myPost("UpdateSiteVisits", { siteId: siteID })
[ later ]
Please ignore my question and answer, I was just getting mixed up with types. Such is the result from me converting from strongly-typed C# to untyped javascript!

Passing custom errors back to AWS API Gateway from AWS Lambda using node.js

I'd really like to be able to pass custom errors back out of my Lambda function via the API Gateway.
I'm generating the errors this way:
if (error) { // failure
APIGatewayResult = { // set error object
statusCode: 608,
message: 'File upload to buffer failed.',
error: error
};
done();
};
I'm fairly certain the format above is either parsed incorrectly or I can't pass it back out like this:
done = (err, res) => callback(null, {
statusCode: err ? APIGatewayResult.statusCode : APIGatewayResult.statusCode,
body: err ? JSON.stringify(APIGatewayResult) : JSON.stringify(APIGatewayResult),
headers: {
'Content-Type': 'application/json',
},
});
I'd like the response I get from API gateway to look like this:
{
"statusCode": 608,
"message": "File upload to buffer failed.",
"error": {}
}
Instead of this:
{
"message": "Internal server error"
}
There are two parts to your question:
1) How to handle Lambda error messages in API Gateway:
There are numerous guides available which explain how to parse Lambda error responses in API Gateway to return them in the desired format to consumers. For example: Error Handling Patterns in Amazon API Gateway and AWS Lambda.
Important to note that you're parsing null to the first parameter of the callback function from your lambda. The first parameter is the error response message, so by providing it as null the Lambda will be returning a successful 200 response back to API Gateway.
2) How to override the generic unhandled exception message in API Gateway:
This is required because as mentioned in the comments, the error you're receiving appears to have been thrown due to an unhandled exception in your application. You'll need to review the logs to identify the source of the issue.
But to change the format of the default error response object you'll need to add a custom Gateway response in API Gateway.
It's difficult to offer a more concrete example given the limited information provided but this should be enough to point you in the right direction to find what you're looking for.

NodeJS SyntaxError: Unexpected token in JSON at position 0

The body of the response from Authorize.net's sandbox API is:
{
"messages": {
"resultCode": "Error",
"message": [
{
"code": "E00012",
"text": "You have submitted a duplicate of Subscription 5777085. A duplicate subscription will not be created."
}
]
}
}
but when I go to parse it:
try {
bodyObj = JSON.parse(body);
} catch (ex) {
console.error(ex);
}
I get this error:
SyntaxError: Unexpected token in JSON at position 0
And this: console.log(response.headers['content-type']);
returns this: application/json; charset=utf-8
What am I doing wrong? I want to parse the JSON into a JS object.
Actually you didn't see it, but there was a invisible unicode character, specifically the byte order mark at the beginning of the JSON.
Since the byte order mark is not a valid JSON character, JSON.parse rejected it.
To remove, use the following code.
function removeByteOrderMark(str){
return str.replace(/^\ufeff/g,"")
}
// OR (faster),
let removeByteOrderMark = a=>a[0]=="\ufeff"?a.slice(1):a
We had the same issue with JSON.parse() in a project we're working on. We're just using JSON.stringfy() and the object was working fine, but on the other platform where we received the data it had a similar error "Unexpected token in JSON at position 1".
Here's how we made it work:
In NodeJs we encoded the stringified object using encodeURI() then sent it
On the client side: decoded the string then used JSON.parse() on the decoded string
Analysis:
I tried to print the characters from the position, then replaced it with an empty string, then we realized it prints other weird characters even after replacing them. After that I realized it's an HTML code """ so instead of replacing it we went for encoding the string it and decoding.
We tried it on our case and it's working no problems

How to pass an object to a GET request?

Hi I'm currently trying to pass an object to a GET request for search filter in nodejs using express but I get a return of 404 GET /route1/search/[object%20Object] 404 1.148 ms - 38
I already try to log the result in the terminal using console.log(req.params.dataObject); or console.log(req.params.dataObject.option); but get the result of [Object, Object] or Undefined
router.get('/search/:dataObject',
async function (req, res) {
try {
console.log(req.params.dataObject);
res.status(200).json(searchPhone);
} catch (err) {
return res.status(404).json({
error: err.message
});
}
});
I expect the result to be {option: 'some data', keyword: 'some data'}
You can't shove an object into a URL without encoding it somehow. Whatever code is calling your server is attempting to do that, and JavaScript is converting the object to a string, which is where the [object Object] comes from. This happens before your server ever gets to it.
What you should probably be doing instead is using the querystring. This is a standard way for you pass in key/value parameters. For example, your client would call:
GET /search?option=some%20data&keyword=some%20data
Then in your server, you could use:
req.query.option
req.query.keyword

Property `message` in error response body cannot be accessed | Hyperledger Fabric

Description
Using node I make a typical API POST request for which I have a .catch block with response variable say err. On error, the response body is returned as such (as seen from the Hyperledger Composer REST app)
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Payment needs to be of positive value)",
"stack": "Error: error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Payment needs to be of positive value)\n at _initializeChannel.then.then.then.then.catch (/home/ubuntu/.nvm/versions/node/v6.11.1/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:839:34)"
}
}
My Issue
I am simply trying to fetch the message property from the above response and send it to the UI. But weirdly err.message does not give me the value I see inside message but returns the entire response body(same with err.stack).
So basically -- err, err.message and err.stack returns the same output
How do I end up fetching only the value inside a property say message ?
PS:
err.statusCode does return the correct value ie. "500".
err.name returns "StatusCodeError"(not "Error" that I see in the response)
OK, so while not really a Hyperledger Composer question - you could try is it response.getBody() ? This is just an example, not a code snippet to use
var finalHost = "yoururl";
var r = new sn_ws.RESTMessageV2();
r.setHttpMethod("get");
r.setEndpoint(finalHost);
//r.setQueryParameter("locatenow", "true");
r.setBasicAuth(username,password);
var response = r.execute();
var responseBody = response.getBody();
// If response is in json format, directly you can send to client.
// If not then convert it.
return responseBody;
// On client side
var newoptions = JSON.parse(jsonstring);
// returned resp.
You might consider something like Restify for error handling on UI side ?
See README at bottom here https://github.com/restify/errors/blob/master/README.md ->
https://www.npmjs.com/package/restify-errors - see this S/O here

Resources