strongloop loopback custom error handling - node.js

I am currently using loopback 3.2.1 The issue I am facing is unhandled error getting logged in the log files when access token expires. Doing google searches I came across this Unhandled error Here it is mentioned that we can have custom error logging middleware. I followed the instructions mentioned there and also referred the document for it. However I am getting the following error :
Error: Cannot apply .../server/middleware.staging.json: The middleware "./middleware/error-logger" in phase "final:after"is not defined in the main config.
current middleware.staging.json:
...
"final": {
"loopback#urlNotFound": {}
},
"final:after": {
"./middleware/error-logger": {},
"strong-error-handler": {
"params": {
"debug": false,
"includeStack": false,
"log": false
}
}
}
server/middleware/error-logger.js:
module.exports = function createErrorLogger(options) {
return function logError(err, req, res, next) {
// your custom error-logging logic goes here
const status = err.status || err.statusCode;
if (status >= 500) {
// log only Internal Server errors
console.log('Unhandled error for request %s %s: %s',
req.method, req.url, err.stack || err);
}
// Let the next error handler middleware
// produce the HTTP response
next(err);
};
}
What am I missing here ?

Finally after looking at the code for loading the config files of loopback figured it out. Loopback is currently reading all the default config files and then merging them with the env specific file. So any configuration changes that need to be made has to be made in the default file with the values being set in the env specific files to make the change behave as required. For example in my case I was trying to add the middleware to the middleware.live.json but did not add it to the the default middleware.json file. So while executing mergePhaseConfig() the values present in the env specific files and searched for in the default file which was not present.
Adding the middleware entry in the default file solved the issue. This is already mentioned in the documents but it skipped my mind today.

Related

Getting name of current express middleware function

Long time reader first time question asker. My question is about dynamically accessing function names in express ^4.17.1. I have poured over both the internet and the express documentation with no luck.
I currently have input validation set up on all of my express middleware functions that ensures I'm getting the right information in the right format. When bad or incomplete information is given to a particular middleware I throw a nicely formatted error to the global error handler and I include the route that errored, the file in which the error occured, and the exact middleware in which it occured.
I've been able to dynamically retrieve both the route and the file name, but I'm having issues finding a way around hard coding in the name of the middleware. I can access the route stack and get the names of ALL middleware in the route, but there doesn't seem to be a way to determine which one you're in aside from keeping that list on res.locals and changing the array as you go (which isn't ideal). Here is a simple example of what I'm talking about.
const path = require("path");
const currFile = path.basename(__filename);
module.exports = {
getStudentAssets(req, res, next) {
const { studentName } = req.body;
if (typeof studentName !== "string") {
const iWouldLoveToGetThisDynamically = "getStudentAssets";
const error = {
status: 400,
log: `ERROR on route ${req.originalUrl} in ${currFile} ${iWouldLoveToGetThisDynamically} middleware`,
};
return next(error);
}
// do random stuff
},
};
I have a feeling there is a way to track which layer you're currently on as accessing req.route.stack looks something like this
[
Layer {
handle: [Function: getStudentAssets],
name: 'getStudentAssets',
params: undefined,
path: undefined,
keys: [],
regexp: /^\/?$/i { fast_star: false, fast_slash: false },
method: 'get'
},
Layer {
// other middleware
}
]
There has to be a way to identify which layer you're currently on, other than keeping a counter stored separately on res.locals that you update every middleware. If you've read this far thank you!
So I figured it out! What I'm doing is basically just rebuilding the trace so all I had to do was access error.stack and it had all the information I could possibly want.

How to catch and save all errors in strapi?

I'm trying to integrate my strapi application with sentry, for which I will need to write a middleware. Use the following documentation: https://strapi.io/documentation/3.0.0-beta.x/advanced/middlewares.html I was able to create a custom middleware with the following:
module.exports = strapi => {
return {
initialize() {
strapi.app.use(async (ctx, next) => {
try {
await next();
} catch (error) {
Sentry.captureException(error)
}
});
}
};
};
However, doing so is preventing strapi to print out the errors to console the usual way but the error is captured by sentry application.
So, my question is: How do I capture the error "seamlessly" and send it to a third party application, at the same time not hinder with the default functioning and error logging of the strapi to console.
Any help would be greatly appreciated!
Thanks :)
EDIT: I figured out that all strapi errors are accessible at the "boom" middleware as pointed out in this file: https://github.com/strapi/strapi/blob/6309af25c921640cb76aeeda463e55db1eb53ef1/packages/strapi/lib/middlewares/boom/index.js#L69
Answer has been given by the authors here: https://github.com/strapi/strapi/issues/4071

express-restify-mongoose error propogation

I am having a problem serving up error messages using express-mongoose-restify.
My schema has a hook like
myschema.pre('save', function(next){
// If validation fails
next(new Error('failed to validate model'))
})
For error handling I have (something similar to) the following code
resify.serve(express.Router(), mongoose.model('myschema', {
onError: function(err, req,res,next){
console.log(err)
res.status(400).json(err)
}
})
The output to the console when validation fails is as follows:
{ [Error: failed to validate model] statusCode : 400 }
In my client I have the following (jquery) ajax error handler:
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
console.log(jqxhr)
console.log(thrownError)
});
thrownErorr is equal to "Bad Request" and jqxhr has reseponseText: "{"statusCode" : 400}" similar (but parsed to JS) for the responseJSON. The message failed to validate model is not being sent to the client. I think that I am misunderstanding the type of object that err is in my sever side error handler. Any thoughts? Thanks in advance!
This is one of those cases where writing the question made me think of the right question to ask myself in order to answer it.
The V8 error object that is use by node does not send the additional information such as the stack, message etc when converted to JSON. My problem was solved by reading up on the properties of the Error object here.
In particular using the following handler, the error is successfully relayed to the client
onError : function(err, req, res, next){
res.status(400).json({
message : err.message,
stack : err.stack
})
}

Node/Express - Can't set headers after they are sent

I have been dealing with this problem now for quite a while, and I can't seem to figure out why it's happening.
I'm getting the Error: Can't set headers after they are sent.
I was able to track down the offending Function Call via the Stack Trace, which leads me to believe that the error lies within this function:
exports.getCardUser = function(req, res, next) {
if (req.user) {
User.cardUser(req.user.userId, function(responseValue) {
res.json(200, responseValue);
});
} else {
res.send(401);
}
};
However, if I hit the Endpoint via a regular REST Client, iex: Hitting the API Endpoint in an Isolated Environment, the Error is not being thrown.
Any ideas?
Edit: skypjack's brought me on the right track - Callback was called twice. Thanks!

Hapi js throwing Error: Already closed

I am using Hapi.js as a framework for our API development, and i am getting following error in very rare scenario.
2015-02-08T12:32:38.073Z - verbose: err.stack > Error: Already closed
at Object.exports.create (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/node_modules/boom/lib/index.js:21:17)
at Object.exports.internal (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/node_modules/boom/lib/index.js:252:92)
at /var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/lib/request.js:297:34
at iterate (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/node_modules/items/lib/index.js:35:13)
at done (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/node_modules/items/lib/index.js:27:25)
at validate (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/lib/auth.js:283:20)
at finish (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/lib/protect.js:45:21)
at wrapped (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/node_modules/hoek/lib/index.js:798:20)
at root (/var/www/ragchewAppServerSrc/ragchew_prod/ragchews/node_modules/hapi/lib/auth.js:198:50)
at /var/www/ragchewAppServerSrc/ragchew_prod/ragchews/src/middlewares/auth/ragchew_auth_strategy.js:75:28
2015-02-08T12:32:38.073Z - verbose: err > {"isBoom":true,"output":{"statusCode":500,"payload":{"statusCode":500,"error":"Internal Server
Neither am able to reproduce this in our testing environment, nor i understand the root cause of this error.
It would be great help if some-one highlight why/when this error is generated by framework.
In our code this error occur when we try to send the reply back from 'Authentication plugin'. We are using basic authentication scheme.
Sample snippet where issue occurs is:
exports.register = function (plugin, options, next) {
plugin.auth.scheme('basic', function (server, options) {
var settings = options;
// some code here
var scheme = {
authenticate: function (request, reply) {
// some code here
// assign access token value to token here.
settings.validateFunc.call(request, token, function (err, isValid, credentials) {
// handle error here.
return reply(null, { credentials: credentials }); // error occurs on this line
});
}
};
return scheme;
});
next();
};
Can you try return reply.continue({credentials: credentials}); on success instead of what you have now?
See this line in hapi-auth-basic for reference:
https://github.com/hapijs/hapi-auth-basic/blob/master/lib/index.js#L83

Resources