How to create an error handling "interceptor" for NodeJS - node.js

So I did a lot of digging around the internet, and I have been unable to come up with the answer to my problem. My goal is that I want to print any errors that are logged to the console into a database. However, I have gone far enough into my project that it would be a pain to go back into my try...catch... blocks and edit them with an error extender, or to just create my own function in the catch area.
I wanted to know: is there a specific way to create an error interception in NodeJS? I mean, I assume that whenever an error is logged to the console, the code fires some sort of event, and I guess I am looking for something like:
process.on(error, async (e) => { // my code here })
Is that at all possible? Is there a module that will allow me to do this? For context, I am running the latest version of Node/NPM on a headless Ubuntu 18.04 server, and am using pm2 to control my program processes.

You can use middleware at the end of the main file of your app
var bodyParser = require('body-parser');
app.use(bodyParser());
...
...
app.use(function(err, req, res, next) {
// Error handler logic
});
You can find more about this in the express documentation https://expressjs.com/en/guide/error-handling.html

Related

Register new route at runtime in NodeJs/ExpressJs

I want to extend this open topic: Add Routes at Runtime (ExpressJs) which sadly didn't help me enough.
I'm working on an application that allows the creation of different API's that runs on NodeJs. The UI looks like this:
As you can see, this piece of code contains two endpoints (GET, POST) and as soon as I press "Save", it creates a .js file located in a path where the Nodejs application is looking for its endpoints (e.g: myProject\dynamicRoutes\rule_test.js).
The problem that I have is that being that the Nodejs server is running while I'm developing the code, I'm not able to invoke these new endpoints unless I restart the server once again (and ExpressJs detects the file).
Is there a way to register new routes while the
NodeJs (ExpressJs) is running?
I tried to do the following things with no luck:
app.js
This works if the server is restarted. I tried to include this library (express-dynamic-router, but not working at runtime.)
//this is dynamic routing function
function handleDynamicRoutes(req,res,next) {
var path = req.path; //http://localhost:8080/api/rule_test
//LoadModules(path)
var controllerPath = path.replace("/api/", "./dynamicRoutes/");
var dynamicController = require(controllerPath);
dynamicRouter.index(dynamicController[req.method]).register(app);
dynamicController[req.method] = function(req, res) {
//invocation
}
next();
}
app.all('*', handleDynamicRoutes);
Finally, I readed this article (#NodeJS / #ExpressJS: Adding routes dynamically at runtime), but I couldn't figure out how this can help me.
I believe that this could be possible somehow, but I feel a bit lost. Anyone knows how can I achieve this? I'm getting a CANNOT GET error, after each file creation.
Disclaimer: please know that it is considered as bad design in terms of stability and security to allow the user or even administrator to inject executable code via web forms. Treat this thread as academic discussion and don't use this code in production!
Look at this simple example which adds new route in runtime:
app.get('/subpage', (req, res) => res.send('Hello subpage'))
So basically new route is being registered when app.get is called, no need to walk through routes directory.
All you need to do is simply load your newly created module and pass your app to module.exports function to register new routes. I guess this one-liner should work just fine (not tested):
require('path/to/new/module')(app)
Is req.params enough for you?
app.get('/basebath/:path, (req,res) => {
const content = require('content/' + req.params.path);
res.send(content);
});
So the user can enter whatever after /basepath, for example
http://www.mywebsite.com/basepath/bergur
The router would then try to get the file content/bergur.js
and send it's contents.

Centralized Error Handling & Reporting for node.js

I want to have a system which will either send me a text message or email based on severity of error on respective occurrence. I have done some research on the subject but I haven't been able to simplify matters.
All in all my end goal is to get notification whenever something is going wrong with my production server. In case of serious issues which are not caught at all I have used process's uncaughtException and for specific routes which are called via separate API calls I can simply use try catch blocks.
My first issue is I cannot handle errors thrown from different routes directly via my main server file.
Second is I'll have to write same kinda' code in every route for exception handling. If something could just listen to all the errors from main server file then I can do things easily.
You can use an error handling middleware in Express:
app.use(function (err, req, res, next) {
console.error(err.stack);
// do whatever you need to send a notification
res.status(500).send('Internal error');
});
See the documentation on the error handling in Express:
https://expressjs.com/en/guide/error-handling.html
Everything you ask about is explained very well there.

Sailsjs fiber integration

Im trying to integrate SailsJS with synchronize, which is based on fibers.
http://alexeypetrushin.github.io/synchronize/docs/index.html
As commented on other fiber libraries, I added a custom middleware to create a new fiber per the request.
var sync = require('synchronize');
...
...
sincronized: function (req, res, next) {
sync.fiber(next);
}
The middleware is executing I can confirm via a console.
But then when I try to do anything fiber related, such as sync.defer() in one of my controllers, I do get an exception.
error: Error getting xxxxxx Error: no current Fiber, defer can't be used without Fiber!
As sailsjs is based in express, adding this middleware should be enough, although I have no idea what I might be missing.
As a side comment, if I create a fiber inside the controller method itself, everything works as expected.
Thanks.

Passing errors to client in express

How do you pass nice error messages to clients in express?
app.use(errorHandler);
function errorHandler(err, req, res, next) {
res.send(err);
}
app.post('/login', usernameIsValid, pwdIsValid, createToken);
In usernameIsValid I create a new Error with a message and status and call next(err). Now this bypasses pwdIsValid and createToken like it should BUT the weird thing is my errorHandler logs the error without a console.log. Am I using the default error handler in express somewhere? How do I turn it off? I have tried both production and development for NODE_ENV.
On the client xhr.responseText is my error.message + what looks like a stack trace? I've even tried just to send err.message but it looks the same.
One way to handle this mess is to make each middleware (if there is an error) create an error string like req.data.err = "invalid username" and then make sure each following middleware checks req.data.err if the string is present. But this is tedious as hell >_<
I solved it. You need to apply the error handler app.use(errorHandler) dead last after all other routes. This disables the built-in error handler. Now you may pass pretty error messages to the client.
Read more here.
edit: process.env.NODE_ENV does not matter.
From the express documentation site
If you pass an error to next() and you do not handle it in an error handler, it will be handled by the built-in error handler; the error will be written to the client with the stack trace. The stack trace is not included in the production environment.
So if you want to avoid the stacktrace you only need to execute your application with the NODE_ENV set to production.
Run you application as follows:
$ NODE_ENV=production node file.js

How do you catch all errors in SailsJS

I'm new to Node and Sails and have been struggling with this problem for a couple of weeks now. I need to log (eventually to a file or database) all errors that occur in our Sails app. I have found a couple of answers that come close to solving this, but none seem to work 100%. I have setup things based off of the answer from this question
When using Sails v0.9.16 I setup my logging in the config/500.js file, but when using test code...
t.t;
... in my controller, Sails just prints out "ReferenceError: t is not defined". It never goes to 500.js. In Sails v0.10.0-rc5 the same test code will get to my custom 500 middleware (shown below).
Problem is in Sails v0.10.0-rc5 it appears that the middleware Router handles 400 error message before getting to my custom 400 middleware.
We have not committed to which version we are going to use, but getting this to work in one or the other would probably make up our minds.
So how do I get all errors that happen? If I am on the right track, what am I missing to get this to work?
Thanks in advance!
Not much code to show for v0.9.16...I don't think I changed anything other than adding a sails.log in the 500.js file...
Below is the custom middleware setup for v0.10.0-rc5 ...
loadMiddleware: function(app, defaultMiddleware, sails) {
// Use the middleware in the correct order
app.use(defaultMiddleware.startRequestTimer);
app.use(defaultMiddleware.cookieParser);
app.use(defaultMiddleware.session);
app.use(defaultMiddleware.bodyParser);
app.use(defaultMiddleware.handleBodyParserError);
app.use(defaultMiddleware.methodOverride);
app.use(defaultMiddleware.poweredBy);
app.use(defaultMiddleware.router); //400s do not make it past this...
app.use(defaultMiddleware.www);
app.use(defaultMiddleware.favicon);
app.use(function(req, res, next ) {
sails.log("400 error caught in middleware - " + err.stack);
next();
});
app.use(function(err, req, res, next){
sails.log("500 error caught in middleware - " + err.stack);
next(err);
});
}
In Sails v0.10, you have custom responses to handle errors, so you don't need to provide custom middleware as in your example. By default, most errors (i.e. those not specifically triggered by res.forbidden(), res.notFound() or another handler) will be served by the serverError response that lives in api/responses/serverError.js. You can customize this to do whatever you like.
If you've upgraded a v0.9 app to v0.10, you might not have the api/responses folder. No problem; just use sails new whatever in an empty directory to generate a new v0.10 project and copy the api/responses folder from the new project to your old one!

Resources