Can I make CherryPy return errors in JSON format? - cherrypy

Is it possible to configure my CherryPy API script to always reply in JSON format?
It's currently returning errors in a HTML page.
Example for what I want a reply to look like:
{
"error": "404",
"title": "page not found",
"message": "blah blah blah the page does not exist. you suck",
}

Yes, you can. Here is a simple implementation
def jsonify_error(status, message, traceback, version):
response = cherrypy.response
response.headers['Content-Type'] = 'application/json'
return json.dumps({'status': 'Failure', 'status_details': {
'message': status,
'description': message
}})
You need to add this tool in the config before starting the cherrypy server
'error_page.default': jsonify_error

Related

How can i get the call-sid from response of callback in twilios AddOn's "IBM Watson"

We enable the Twilios AddOn "IBM Watson Speech to Text" for recording transcribe.and we set our server webhook while enabling the addon. Now twilio calling webhook once call is completely done. after completing call twilio give response in that webhook In Nodejs.For handling that call response we need "Call Sid".In webhook response we cannot get "callSid".So how we can identify that response is for this particular call...?
anyone help me to how can find call-sid in response?
Callback response is
{
"status": "successful",
"message": null,
"code": null,
"results": {
"ibm_watson_speechtotext": {
"request_sid": "**************",
"status": "successful",
"message": null,
"code": null,
"payload": [{
"content_type": "application/json",
"url": "*************/Data"
}],
"links": {
"add_on_result": "***********/Accounts/********/Recordings/**********/AddOnResults/******",
"payloads": "https://api.twilio.com/2010-04-01/Accounts/******/Recordings/*******/AddOnResults/******/Payloads",
"recording": "https://api.twilio.com/2010-04-01/Accounts/******/Recordings/*******"
}
}
}
}
Thank you for help
When you get the Add-on result it comes as part of the Twilio voice webhook, with all the normal request parameters as well as an extra AddOns parameter which contains the JSON that you have shared above.
Webhook requests from Twilio are in the format application/x-www-form-urlencoded and then within the AddOns parameter the data is a JSON string. In a (Ruby-like) pseudo code, you can access the call sid and the add on data like this:
post "/webhook" do
call_sid = params["CallSid"]
add_on_json = params["AddOns"]
add_on_data = JSON.parse(add_on_json)
# return TwiML
end

Unable to parse Response message using node-fetch

My goal is to read the message that is returned within the response. I am using node-fetch and the response is gzipped. This is what I have so far:
const response = await fetch(config.url, {
method: 'POST',
body: request,
headers: {'Content-Type': 'application/json; charset=UTF-8', 'x-tn-api_key':config.key, 'x-tn-api_signature':generateAPISignature()}
})
let deserializedResponse = await response.json()
This is what deserializedResponse looks like:
{
"timestamp": "2021-03-03T22:34:37.362+0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Cannot deserialize instance of `xyz` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `xyz` out of START_ARRAY token\n at [Source: (PushbackInputStream); line: 1, column: 1]",
"path": "/a/v1/events"
}
There is json parse error in message field, how can I read the message field? Essentially if the call fails, I want to log the message for debugging purposes.
Update: I hard coded request object to some static object and still getting the same error. When I copy paste the same static object into Postman it works fine. Does anyone know why body:request is being read as an array of requests? Seems that is the reason for the error, because it is expecting an object in the request, not an array of objects
Replacing
body: request,
with
body: JSON.stringify(request),
seemed to fix it

How to deal with errors in ExpressJS rest API

I am confused whether I should just console.log out the error, or should I return the error to my front end. Could someone tell me what the best practice is?
For example, right now, if it is a error with status code 400, I just console log unable to create playlist. So, should I let it be or should I change it to return res.status(400).send(err). What are the pros and cons for both?
try {
playlist_id = await create_playlist(req, res, spotifyAPI);
console.log('created');
} catch(err) {
if (err['statusCode'] === 401) {
req.logout();
console.log('authentication code reset');
return res.status(401).send(err);
}
else {
console.log('error - unable to create playlist');
}
}
The error handling depends upon specific use cases and a contract is fixed and followed by the APIs. Various response formations could be used for error handling.
Error handling with an appropriate status code.
eg: Respond with 404 for conveying that the requested resource does not exist.
Create an error object which shows the details of the error. Custom error codes could be included to handle specific handling on the frontend.
{
"status": 401,
"error": "ERR-AUTH-001",
"message": "Username does not exist",
"detail": "Ensure that the username entered is correct"
}
Maintain a standard response body from the backend.
{
"status": 401,
"errors": [{
"errorcode": "ERR-AUTH-001",
"message": "Username does not exist",
}],
detail: "Ensure that the username entered is correct"
}
or
{
"status": 401,
"success": false,
"error": {
"errorcode": "ERR-AUTH-001",
"message": "Username does not exist",
"detail": "Ensure that the username entered is correct"
}
}
You could use the former if various errors are to be reported in a response.
Example: Google standard for Search Ads 360 API
There is no best practice but if you want your front to have a special behaviour on this error you should return your 400 status code.
If not, just log it but your front won't be alerted.
Usually, you don't want to send the whole error object to your front as it'll will give some hint to potential hacker, so you want to log the error message on your server (it can be in a file or a log manager like ELK stack or a simple database) and just return a status code to your front. You can then define a "user-friendly" error message in your front.
Exemple : User fail to authenticate giving the right login but the wrong password, you return a 400, your front display 'invalid credentials'

Gmail api send with Postman

I am trying to send a mail using gmail API with POSTMAN, using POST Method
POST https://www.googleapis.com/upload/gmail/v1/users/example#gmail.com/messages/send
but I get an error below:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalidArgument"
"message": "Recipient address required"
}
],
"code": 400,
"message": "Recipient address required"
}
}
header is already putted Content-type: message/rfc822
I know that this has to be encoded into base64(web_safe), so I translated
"From: sender.example#gmail.com\r\n" +
"To: receiver.example#gmail.com\r\n" +
"Subject: Subject Example\r\n" +
"This is content: hope you got it\r\n"
I also replaced them to be web_safe
replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
so I got an base64 like below.
so I put raw in body of POST METHOD
{
"raw": "RnJvbTogc2VuZGVyLmV4YW1wbGVAZ21haWwuY29tDQpUbzogcmVjZWl2ZXIuZXhhbXBsZUBnbWFpbC5jb20NClN1YmplY3Q6IFN1YmplY3QgRXhhbXBsZQ0KVGhpcyBpcyBjb250ZW50OiBob3BlIHlvdSBnb3QgaXQNCg"
}
I used 'try this api' on google developers' site, and I could send it.
https://developers.google.com/gmail/api/v1/reference/users/messages/send
But with POSTMAN, I cannot.
Any help please?
This mean, data format is incorrect. You should try below method which perfectly worked for me.
I use below format.
From: <FROM#gmail.com>
To: <TO#gmail.com>
Subject: Test Email
Test
For testing purpose, I used https://ostermiller.org/calc/encode.html to 64encode above text message. So I will get encoded string as below
IEZyb206IDxGUk9NQGdtYWlsLmNvbT4KICAgIFRvOiA8VE9AZ21haWwuY29tPgogICAgU3ViamVjdDogVGVzdCBFbWFpbAogICAgCiAgICBUZXN0
Now in postman,
Gmail Rest API URL you have to use https://www.googleapis.com/gmail/v1/users/<YOUR#gmail.com>/messages/send
Content type should be json because you send json format in message body.
Content-Type: application/json
In body
{
"raw": "IEZyb206IDxGUk9NQGdtYWlsLmNvbT4KICAgIFRvOiA8VE9AZ21haWwuY29tPgogICAgU3ViamVjdDogVGVzdCBFbWFpbAogICAgCiAgICBUZXN0"
}
So finally postman looks like as below.
Once you send a request to API, You will receive response looks like this
{
"id": "172016110a227c19",
"threadId": "172016110a227c19",
"labelIds": [
"UNREAD",
"SENT",
"INBOX"
]
}
I think that you should set the Content-type header to application/json. Also, don't forget to add the Authorization header.
If you want more details please refer below link:
How to send a message successfully using the new Gmail REST API?
If you want more details please refer below link: Gmail API send message without using Base64 encode

Express/node.js 204 HTTP code response issue

Here is my code:
.put(function(req, res) {
User.findById(req.params.user_id, function(err, user) {
if(err) return res.send(err);
user.dateEdited = new Date();
user.save(function(err) {
if(err) return res.send(err);
return res.status(204).json(customHTTPcodeReponses.updated(user))
});
});
});
Part of my middleware called customHTTPcodeReponses
updated: function(data) {
return {
code: 204,
status: 'Success',
message: 'Resource updated (or soft deleted)',
data: data
};
}
I as figured out, 204 is not supposed to return any data, so I am not getting any back.
But I would like to have this data to see what was really changed. How could I hande response code then?
Have in mind that if I use
res.status(200).json(customHTTPcodeReponses.updated(user))
data is shown.
If you need some extra explanation, please ask.
yes, you are correct. This http status not allowed messages because it means "No Content". If you send content, use other statuses. For details look at document: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
There is part: "The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields."
If you want to send not content but metadata with addictional info, in this document there is part : "The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.". I think it is formal answer for your question.
If you not so formal, use status '200' with metadata as content.
edit:
to send data in header :
res.header(field, [value])
It is simple. If you need some data back, just use return code 200 and return that data. If you don't need send back any data, use 204. You can set header with 204 to indicate operation status or url like Location with return code 201, but I am not sure this is a good idea.
yes if you have to send response message the use 200 or you can also use 404
because of 204 return no message in body

Resources