I wanted to know does YUI3 provides any way to try and catch errors functionality, where in after the error is captured we can show some customized error alert and simultaneously log the error at server side with the error exceptions and other details.
Also if this functionality is not there in yui3 then which all frameworks do one need to use to do this and which all are compatible with YUI.
I'm not aware of YUI3 providing exactly what you're after out-of-the box.
You can split your question into two parts:
Capturing errors
You either wrap your code with try/catch blocks or use a global error handler. It looks like YUI3 doesn't yet directly handle this (http://yuilibrary.com/projects/yui3/ticket/2528067) but handling it shouldn't be too hard, you'll just have to test for browser differences.
Sending Error data to the server
You ought to be able to use Y.IO to send back the error data to the server. It looks like you get errorMsg, url, lineNumber given to you, so you can just send them back to the server:
YUI().use("io-base",function(Y){
window.onerror = function(errorMsg, url, lineNumber){
Y.io("/errorHandler.php", {
data: {
errorMsg: errorMsg,
url: url,
lineNumber: lineNumber
}
});
alert("Sorry, something bad happened");
};
console.log("handler registered");
//now trigger an error
a.b.c="banana";
});
That seems to work here: http://jsfiddle.net/J83LW/
I'l leave the customized alert to you, I've left an alert here as a basic example of handling this
Related
I am using strongloop 4 (lb4). I am facing one issue that in error object I need to one more custom parameter in the error object.
I want it on the global level. On every error, I want to add that custom parameter in every error message.
In loopback4 global error handling is done by src/sequence.ts.
Suppose the error message object is.
{
"error": {
"statusCode": 400,
"name": "xyz",
"message": "firstName is required"
}
}
I want error object output like.
{
"error": {
"customParam" : "customParam",
"statusCode": 400,
"name": "xyz",
"message": "firstName is required"
}
}
Cross-posting the answer I gave on GitHub in https://github.com/strongloop/loopback-next/issues/1867#issuecomment-434247807
Building HTTP error responses is a tricky business. It's easy to get it wrong and open your application to attacks.
In LoopBack (both 3.x and 4.x), we use our strong-error-handler middleware to take care of this. See Handling Errors in our docs.
Here are the important security constraints to keep in mind:
In production mode, strong-error-handler omits details from error responses to prevent leaking sensitive information:
For 5xx errors, the output contains only the status code and the status name from the HTTP specification.
For 4xx errors, the output contains the full error message (error.message) and the contents of the details property (error.details) that ValidationError typically uses to provide machine-readable details about validation problems. It also includes error.code to allow a machine-readable error code to be passed through which could be used, for example, for translation.
In debug mode, strong-error-handler returns full error stack traces and internal details of any error objects to the client in the HTTP responses.
Now that I have warned you, LoopBack 4 makes it very easy to format the error messages your way. Just provide a custom implementation of the Sequence action reject. See Customizing Sequence Actions in our docs, it explain how to create a custom send action. The solution for reject is pretty much the same, you just need a different signature for the action function.
export class CustomRejectProvider implements Provider<Reject> {
// ...
action({request, response}: HandlerContext, error: Error) {
// handle the error and send back the error response
// "response" is an Express Response object
}
}
Caveat: some errors thrown by LB4 have only code set, these errors need a bit of pre-processing to decide what HTTP status code they should trigger. (For example, the error code ENTITY_NOT_FOUND should be mapped to the status code 404). The built-in reject action does not yet expose this pre-processing for consumption by custom reject actions. It's an oversight on our side, l created a new issue https://github.com/strongloop/loopback-next/issues/1942 to keep track of that.
I tried adding error object into new object.
let error = new Error();
error.name = 'Invalid_OTP_AttemptsError';
error.status = 422;
error.message = 'You’ve exceeded the maximum number of One-Time Password (OTP) attempts';
let data={...error};
data.retryCount=foundMb.retryCount
data.resendCount=foundMb.resendCount
return callback(null,data);
I'm currently writing a public REST service in Node.js that interfaces with a Postgres-database (using Sequelize) and a Redis cache instance.
I'm now looking into error handling and how to send informative and verbose error messages if something would happen with a request.
It struck me that I'm not quite sure how to handle internal server errors. What would be the appropriate way of dealing with this? Consider the following scenario:
I'm sending a post-request to an endpoint which in turn inserts the content to the database. However, something went wrong during this process (validation, connection issue, whatever). An error is thrown by the Sequelize-driver and I catch it.
I would argue that it is quite sensitive information (even if I remove the stack trace) and I'm not comfortable with exposing references of internal concepts (table-names, functions, etc.) to the client. I'd like to have a custom error for these scenarios that briefly describes the problem without giving away too detailed information.
Is the only way to approach this by mapping every "possible" error in the Sequelize-driver to a generic one and send that back to the client? Or how would you approach this?
Thanks in advance.
Errors are always caused by something. You should identify and intercept these causes before doing your database operation. Only cases that you think you've prepared for should reach the database operation.
If an unexpected error occurs, you should not send an informative error message for security reasons. Just send a generic error for unexpected cases.
Your code will look somewhat like this:
async databaseInsert(req, res) {
try {
if (typeof req.body.name !== 'string') {
res.status(400).send('Required field "name" was missing or malformed.')
return
}
if (problemCase2) {
res.status(400).send('Error message 2')
return
}
...
result = await ... // database operation
res.status(200).send(result)
} catch (e) {
res.status(500).send(debugging ? e : 'Unexpected error')
}
}
Background: In Node, it is common to pass an error object to a callback function in async calls as well explained in Error handling in Node.js by Joyent. A standard error object contains a name, a message, a stack trace and possible additional properties. Passing or throwing strings or plain objects as errors is considered a bad practice. With Socket.io, data can be transmitted from client to server and vice versa by emitting events and having an optional response callback. This opens up multiple ways to pass and handle errors.
Question: If a socket.io event from a client causes an error on the server, what is the best practice to inform the client about this? A plain error object in response? A separate error event and listener? How the error should be structured? Is there any best practices like is the case with Node? What are you using?
Example: Imagine socket.io used for login. A client logs in by emitting a username and a password like below:
socket.emit('login', {user: 'Foo', pass: 'Bar'}, function (response) {
...
});
On a successful login, the response contains a session token. But what if the username or the password do not match? Several approaches come to mind:
Approach 1 - plain error object: The response could contain a property error having a plain error-like object as its value, with standard name and message properties and possible additional ones:
{
error: {
name: 'InvalidUsernameOrPasswordError',
message: 'Username or password was invalid.',
usernameExists: false
}
}
The client thus tests if response contains an error and if not, continues with the login procedure:
socket.emit('login', {user: 'Foo', pass: 'Bar'}, function (response) {
if (response.hasOwnProperty('error')) {
// handle error
}
// do something with response.token
});
Approach 2 - simple string: Similar to Approach 1, but the error property is just a plain string representing the name of the error.
{
error: 'InvalidUsernameOrPasswordError'
}
This approach is light and sufficient in this naïve example but lacks ability to pass additional data about the error.
Approach 3 - separate event: The server could emit and the client listen additional events to handle possible outcomes:
socket.on('loginError', function (error) {
// handle error based on error.name and error.message
});
socket.on('loginSuccess', function (data) {
// handle successful login with data.token
});
socket.emit('login', {user: 'Foo', pass: 'Bar'});
This approach feels the most explicit and pure under the event emitting paradigm but requires multiple event handlers.
Conclusions: There seem to be many possible ways to pass and handle errors. Any experiences, thoughts or feels?
It depends on your "clients". If you have end users like people using an application they really don't care so much about how you send the error. At the end you are going to have a text on the frontend saying they are wrong. So you are the one who have to select which way you prefer for implementing the error handling on the backend.
If your clients are not end users like the case above, imaging you are creating an application or library and you have to say there was an error. You should return as much as information you can in order for people who use your application identify where you error is.
So at the end:
-For customers: You will show your errors on the frontend so that ups to you how you want manage the error.
-For developers: You should show as many error information as you can. Showing the stack trace, error code...
I am trying to understand how to build my error handling system for my api.
Let's say I have a the following line in a controller method :
var age = json.info.age;
with
json = {"id":1, "name":"John", info": {"age":27, "sex":"m"}}
Let's say that the object doesn't contain an info field, I'll get the following error TypeError: Cannot read property 'info' of undefined and my server will crash.
Is there a way to make a higher level abstraction and catch all the potential errors that I could have? Or should I have a try/catch system for each of the methods of my controllers?
BEWARE OF THE CODE BELOW, IT WILL BITE YOU WHENEVER IT CAN!
Don't use the code snippet below if you do not understand its
implications, please read the whole answer.
You can use the node way for uncaught errors. Add this in your config/bootstrap.js
Updated the snippet below to add what was said in the comments, also added a warning about using a global to respond to the user.
process.on('uncaughtException', function (err) {
// Handle your errors here
// global.__current__ is added via middleware
// Be aware that this is a bad practice,
// global.__current__ being a global, can change
// without advice, so you might end responding with
// serverError() to a different request than the one
// that originated the error if this one happened async
global.__current__.res.serverError();
})
Now, can doesn't mean should. It really depends on your needs, but do not try to catch BUGS in your code, try to catch at a controller level the issues that might not happen every time but are somehow expected, like a third-party service that responded with empty data, you should handle that in your controller. The uncaughtException is mainly for logging purposes, its better to let your app crash if there is a bug. Or you can do something more complicated (that might be better IMHO), which is to stop receiving requests, respond to the error 500 (or a custom one) to user that requested the faulty endpoint, and try to complete the other requests that do not relate to that controller, then log and shutdown the server. You will need several instances of sails running to avoid zero downtime, but that is material for another question. What you asked is how to get uncaught exceptions at a higher lvl than the controllers.
I suggest you read the node guide for error handling
Also read about domains, even thought they are deprecated you can use them, but you would have to deal with them per controller action, since sails does not provide any help with that.
I hope it helps.
You can check this way if you want to:
if (object != null && object.response != null && object.response.docs != null){
//Do your stuff here with your document
}
I don't really get what is your "object" variable in the first place, so i don't know if you can check it at a different level, is it a sails parameter to your controller ?
So that's how I did it, thanks to Zagen's answer.
module.exports.bootstrap = function(cb) {
process.on('uncaughtException', function (err) {
//Handle your errors here
logger.fatal(err);
global.__current__.res.serverError();
})
cb();
};
I send a generic error 500 to the user if any uncaught exception is thrown, and I log the error to the fatal level. On that way, my server is still accessible 24/7 and I can monitor the logs at another level and trigger an alarm on a fatal error. I can then fix the exception that was thrown.
I am very new to node.js and express.js and in programming concepts. I already made a basic MVC modeled app on node and express.
My problem is how do you handle error, I got this following code:
exports.submitBloodRequest=function(kaiseki,resView,request){
var params = {
bloodCenterId:request.session.centerID,
bloodTypeId: request.body.bloodType,
requestQuantity:request.body.numberOfDonors
}
kaiseki.createObject('blood_center_request', params, function(err, res, body, success) {
if(success){
resView.redirect('/bloodRequest')
}else{
//WHAT TO DO HERE?
}
});
}
Kaiseki is just a middleware for parse.com, I don't know what to do if it got error. Usually I use ajaxForm.js to look for BadRequest then use javascript to display error message in my view.
I want my error to appear in the same page, where it is success, should I pass a json error to my view?
Or still use ajaxForm.js and instead of res.render or res.redirect I should use res.status(500)
Is there anyway to handle the error and showing it into the view. Without using any javascript to detect BadRequest?
And can a view have a optional variable? In my view If I didnt pass any value on it it gives me error like if i have #{variable} it asks for its value. Can it be made to be optional? Im using Jade Template
To respond to an XHR request with an error you can do something like return resView.status(500).send(err); which will send the err object back as JSON. If you want to render an HTML error page instead you can do return resView.status(500).locals({err: err}).render('/errorPage');
You didn't say which template engine you are using but most likely the #{} version will automatically escape HTML characters for you (turn < into <, etc) to avoid XSS attacks and rendering problems whereas !{} will render the contents of the variable directly without escaping, which is dangerous if the variable contains any user-generated content, but necessary if the variable has HTML you want rendered by the browser.