expressjs / express

Fast, unopinionated, minimalist web framework for node.
https://expressjs.com
MIT License
65.81k stars 16.46k forks source link

Extension to add Global Error Handler/Response Handler #5249

Open shravan20 opened 1 year ago

shravan20 commented 1 year ago

Idea:

Add an option to extend a internal global error handler and response envelope wrapper.

This basically wraps the response into a wrapper and automatically takes care of the error and how's it wrapped into json.

Like wise for success responses too.

sbrsubuvga commented 1 year ago

` app.use(function(err,req,res,next){ if(err.name=='UnauthorizedError') { return res.status(401).send({status:'error',msg:'Authentication failed'}); } else{ return res.status(500).send({status:'error',msg:'Internal Server Error'}); }

})`

kisshan13 commented 10 months ago

Don''t worry i'm working on same. A package named exhancer you can check here... https://github.com/kisshan13/exhancer.js

IamLizu commented 4 months ago

Could you please provide some code sample so it helps people what is expected?

@UlisesGascon can we please add awaiting more info label here?

kisshan13 commented 4 months ago

Sure, the basic idea is to have different error handlers for specific errors. Let's say someone is using mongoose they might get duplicate entry errors or things like that or someone using zod can get validation errors. So errors like this can be easily globally managed if we somehow make different error handlers.

A sample error handler.

export default function mongoError(error) {
    if (error instanceof mongoose.mongo.MongoServerError) {
        switch (error.code) {
            case 11000:
                const alreadyExists = Object.keys(error?.keyPattern);
                return {
                    status: 400,
                    message: `${alreadyExists.join()} already exists`,
                };

            default:
                return {
                    status: 500,
                    message: "Internal server error",
                };
        }
    }
}

Making a error handler middleware

export function errorHandler(handler) {
    let errMessage = "";
    let errStatus = 0;

    return (err, req, res, next) => {
        for (let i = 0; i < handler?.length; i++) {
            const result = handler[i](err);

            if (result?.message || result?.status) {
                errMessage = result?.message
                errStatus = result?.status
                break;
            }
        }

        res.status(errStatus || err?.status || 500).send({
            status: errStatus || err?.status || 500,
            message: errMessage || err.message
        })
    }
}

Adding it to express global error handler :

app.use(errorHandler([mongoError]))

So this is the basic idea which i have . : )

IamLizu commented 4 months ago

Hey @kisshan13 👋

What I normally do is have map for error and handlers; with an observer, I simply extend the default global error handler that express provides and react accordingly.

Your approach looks good to me, and I understand provided code can be pseudo. However, maybe use Array.prototype.some instead of a for loop to handle the handlers more idiomatically?