Modify a sailsjs/nodejs error object - node.js

I have pasted a callback below that is in my waterline model
In order to give the client a pretty message I'm attempting to modify the status of the error object so that res.negotiate(err) will respond with badRequest. But my error.status = 400 seems to be ignored and when its passed to res.negotiate I still get 500 error returned (server error instead of bad request).
I'm working off of these docs
http://sailsjs.org/#/documentation/reference/res/res.negotiate.html
https://docs.nodejitsu.com/articles/errors/what-is-the-error-object
http://massalabs.com/dev/2013/10/17/handling-errors-in-nodejs.html
Thoughts, bug?
beforeDestroy: function(criteria, next){
var error = new Error('This shift has people scheduled and can not be deleted.');
error.type = 'user';
error.status = 400;
return next(error);
}
Also, even when I get a Server Error returned the message. In this case "This shift has people scheduled ..." can not be found on the error object that is returned? I'm using the unmodified response pages and I don't know why its being stripped out?
This is the error object being returned to the client.
error: "E_UNKNOWN"
raw: {}
status: 500
summary: "Encountered an unexpected error"

Looking at the source of the negotiate response, it appears that a 400 response should be returned:
'node_modules\sails\lib\hooks\responses\defaults\negotiate.js'
try {
statusCode = err.status || 500;
// Set the status
// (should be taken care of by res.* methods, but this sets a default just in case)
res.status(statusCode);
} catch (e) {}
// Respond using the appropriate custom response
if (statusCode === 403) return res.forbidden(body);
if (statusCode === 404) return res.notFound(body);
if (statusCode >= 400 && statusCode < 500) return res.badRequest(body);
I would suggest setting a break point within the negotiate response to verify it being called from the beforeDestroy model lifecycle callback.

Related

Why does app.put always return status code 200 when res.status(400)

I have this piece of code:
app.put("/:id", async (req, res) => {
let id = req.params.id;
// validate id
if(id < 0 || isNaN(id)) {res.send(Helper.ID_ERROR).status(400); return;}
// check if id exists
let sensorValueById = await sensorValue.getById(id);
if (sensorValueById.length == 0) {
res.send(Helper.NOTHING_FOUND_ERROR).status(404);
return;
}
let sensorValueBody = req.body;
if (!checkProperties(properties, sensorValueBody)) {
res.send(Helper.INVALID_PROPERTIES_ERROR).status(400);
return;
}
sensorValueBody.id = id;
res.send(await sensorValue.update(sensorValueBody));
})
When I access this route and make a mistake on purposes I get the correct message: Id must be number and positive!, but the status code is 200 and not 400
Same for the 2 error responses below it always returns 200 as status code but the right message.
When I use sendStatus instead of status I get this error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I understand what it means but I don't know why it sends some other header before it, and I don't know where it sends it before
Firstly; Errors in Node.js are handled through exceptions. An exception is created using the throw keyword.
See here for more information. Error handling in Node.js
The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
res.send([body]) Sends the HTTP response.
res.status(code) Sets the HTTP status for the response.
See here for more information about express response.
Your answer here:
res.status(400).send(Helper.ID_ERROR)
res.status(404).send(Helper.NOTHING_FOUND_ERROR)
res.status(400).send(Helper.INVALID_PROPERTIES_ERROR)
Just call .status(XXX) before .send({}) on the Reply object

Why does Node.js specify error.code for Errors but response.statusCode for Response?

I am getting myself confused between code and status working with Node.js and Express.
When I create an Error() I do this for example:
const Err = new Error();
Err.message = "Login failed";
Err.code = 401; // why is this not Err.statusCode or Err.status ?
throw(Err);
Returning that via Express ends up becoming:
catch (error) {
return res.status(error.code).send(error.message);
}
The Express.js documentation says that res.status is an alias of Node's response.statusCode.
So why is the same code expressed in three different ways: error.code, response.statusCode and res.status. Why isn't it consistently the same?
Essentially the code and status you're talking about refer to two different concepts.
1 - The Error class code property refers to a standard node.js concept and is not http-specific - just like the Error class iteself.
This is what node's documentation says about it:
The error.code property is a string label that identifies the kind of error.
If you want an Error object representing a http error to actually hold a http status information, then nothing prevents you from adding a dedicated custom status - or statusCode - property. A httpError value for the code property would probably be more fitting in this case since it refers to a higher-level concept than a more fine-grained http status.
2 - response.statusCode and response.status on the other hand are both http specific and relate to the http status of a http.ServerResponse object. The http.ServerResponse class is defined by node.js, and res.status is just a shorthand setter that is added by express for conveniency - and couldn't possibly be named after the same name as the property it serves as a setter for.

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

Changing status code changes response body in Express

So I have a pretty simple helper function to send errors in my response. I use this function all over my codebase:
exports.error = function (err, res) {
res.send({
success: false,
errorMsg: err.message,
errors: err.errors == null ? [] : err.errors
});
};
I decided to add a status code to it:
exports.error = function (err, res, status) {
res.status(status).send({
success: false,
errorMsg: err.message,
errors: err.errors == null ? [] : err.errors
});
};
If the status is 200 I get the body exactly like the object passed to the send method. The problem is that if status is different from 200 (400 or 500 for example) my response body changes to:
{
config: Object
data: Object
headers: function (d)
status: 500
statusText: "Internal Server Error"
}
And my original response body (the one with success, errorMsg and errors fields) is inside this new response under the data attribute. I have no idea why this is happening but as far as I know I don't have any other custom error handlers in my application. I don't want this behavior and instead I want only my original response body.
I am using the body-parser package, but I believe that it only affects the requests, not the responses.
The response object that you're getting is Angular's response object (see the documentation):
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
AFAIK, when Angular receives a successful HTTP response (like a 200), it will run any of the default transformations to convert the response to, say, a JS object (from a JSON response).
However, it won't do that when the HTTP response indicates an error. In that case, you will get the above-mentioned response object back.
Thanks to #robertklep I found out that the problem was actually in my Angular code that handled errors. Instead of returning the response body my Angular error handler was returning the error itself.

Express Error Handling - Get Status Code

If I define error handling middleware with express like so:
app.use(function(err,req,res,next){
// Do Stuff
});
How do I get the HTTP status code of the error(or do I just assume is's a 500)?
Thanks,
Ari
In short, your code has to decide the appropriate error code based on the specific error you are handling within your error handling middleware.
There is not necessarily an HTTP status code generated at this point. By convention, when I call next(error) from a middleware function or router handler function, I put a code property so my error handling middleware can do res.status(err.code || 500).render('error_page', error); or something along those lines. But it's up to you whether you want to use this approach for your common 404 errors or only 5XX server errors or whatever. Very few things in express itself or most middleware will provide an http status code when passing an error to the next callback.
For a concrete example, let's say someone tried to register a user account in my app with an email address that I found already registered in the database, I might do return next(new AlreadyRegistered()); where the AlreadyRegistered constructor function would put a this.code = 409; //Conflict property on the error instance so the error handling middleware would send that 409 status code. (Whether it's better to use error handling middleware vs just dealing with this during the normal routing chain for this "normal operating conditions" error is arguable in terms of design, but hopefully this example is illustrative nonetheless).
FYI I also recommend the httperrors npm module which provides nicely-named wrapper classes with a statusCode property. I have used this to good effect in a few projects.
You could try to define the status code in the route:
app.get('/force-error', function(req, res) {
res.status(400)
next(new Error('Bad Request.'))
})
Then:
server.use(function serverErrorHandler (err, req, res, next) {
const code = res.statusCode
// if status 200 change to 500, otherwise get the defined status code
res.status(code === 200 ? 500 : code)
// check if it's a ajax request
if (req.xhr)
res.json({
error: {
status: res.statusCode,
message: err.message,
stack: err.stack,
}
})
else
next(err)
})

Resources