首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用类型记录在express中创建错误处理程序中间件?

如何使用类型记录在express中创建错误处理程序中间件?
EN

Stack Overflow用户
提问于 2022-03-26 18:17:28
回答 1查看 641关注 0票数 -2

通过使用Express和TypeScript,我试图创建一个中间件来捕获像Sentry这样的错误,代码如下:

代码语言:javascript
复制
 const catchError = (
  error: Error,
  req: Request,
  _res: Response,
  next: any
) => {
   console.log("ERROR: ", error);
   //some logic

  next(error);
}

index.ts

代码语言:javascript
复制
  app.use(bodyParser.json({ limit }));
  app.use(morgan("[:date[iso]] :method :url :status :response-time ms"));

  app.use(express.json());
  app.use(cors({ credentials: true, origin: true }));

  app.use(bodyParser.urlencoded({ extended: false }));
//controllers

app.use(catchError as express.ErrorRequestHandler)

为什么我的中间件只在我输入:

代码语言:javascript
复制
} catch (error) { 
   next(error);
}

在有错误的函数中,没有错误就不能工作?该中间件还应该不使用next(error)捕获错误和异常。

EN

回答 1

Stack Overflow用户

发布于 2022-03-26 19:04:58

  1. 首先需要创建一个自定义错误类,扩展基本错误类
  2. ,您必须使类具有灵活性,以便能够接受您希望传递给
  3. 的错误代码,创建中间件来处理错误。至于我的,我有一个设置,处理一些密码验证和猫鼬错误。希望您也可以在这里扩展功能,以满足您的需要,

扩展基错误的自定义错误类

代码语言:javascript
复制
interface IErrorResponse {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    [prop: string | symbol]: any
    statusCode?: number
    message: string
    code?: number
}

class ErrorResponse extends Error implements IErrorResponse {
    public statusCode: number;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    [prop: string]: any
    constructor(message: string, statusCode: number) {
        super(message)
        this.statusCode = statusCode
    }
}

export default ErrorResponse

中间件

代码语言:javascript
复制
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Request, Response, NextFunction } from "express"
import capitalize from "../utils/capitalize"
import ErrorResponse from "./ErrorResponse"

export default function (
    err: ErrorResponse,
    req: Request,
    res: Response,
    next: NextFunction,
): Response<any, Record<string, any>> {
    let error: ErrorResponse&{[key:string]:any} = { ...err }
    error.message = err.message
    // console.log(err)
    if (err.code === 11000) {
        const message = Object.keys(err).map((k) =>
            capitalize(`${k} already exist`),
        )
        error = new ErrorResponse(String(message), 400)
    }
    if (err.name === "ValidationError") {
        const message = Object.keys(err).map(function (value) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            return typeof value === "object" ? error["message"] : value
        })
        console.log("Parsing ", message)

        error = new ErrorResponse(String(message), 400)
    }

    if (error.message.split(/\n/).length > 1) {
        return res.status(error.statusCode || 500).json({
            success: false,
            message:
                error.message
                    .replace(/\t/, "")
                    .split("\n")
                    .filter((e) => e !== "") || "Internal server error",
        })
    }
    return res.status(error.statusCode || 500).json({
        success: false,
        message: error.message || "Internal server error",
    })
}

在这里,这些可能是您可以捕获的错误,我有这个密码验证器,它会在错误上追加一些字符串,并使用\n终止每个错误,这样错误处理程序就能够拆分错误并给出一个JSON格式的错误列表。

代码语言:javascript
复制
passwordRegex = function ({
        props,
        fields,
    }: {
        props: { [x: string]: string },
        fields: { fieldName: string, name: string }[],
    }): { passOK: boolean, errors: string } {
        let errors = ""
        try {
            for (let key of Object.keys(props)) {
                if (fields.some((f) => f.fieldName === key)) {
                    const regex = new RegExp(props[key], "i")
                    const field = fields.find((f) => f.fieldName === key)
                    if (regex.test(props!["password"])) {
                        errors += `Password should not contain your ${field!.name}\n`
                    }
                }
            }
            if (!/[a-z]/.test(props["password"])) {
                errors += "Password must contain at least 1 lowercase letter\n"
            }
            if (!/[A-Z]/.test(props["password"])) {
                errors += "Password must contain at least 1 uppercase letter\n"
            }
            if (!/[0-9]/.test(props["password"])) {
                errors += "Password must contain at least a number\n"
            }
            if (!/[\w]{7,16}/.test(props["password"])) {
                errors += "Password must be at least 8 characters long\n"
            }
            if (/[.*+?^${}#%^@!`()|[\]\\]{4,}/.test(props["password"])) {
                errors +=
                    "Password must not contain more than 4 repeating characters\n"
            }
            if (!/[.*+?^${}#%^@!`()|[\]\\]/.test(props["password"])) {
                errors +=
                    "Password must be at least 1 special character (.*+?^${}#%^@!`())\n"
            }
            if (errors !== "") {
                return { passOK: false, errors }
            }
            return { passOK: true, errors }
        } catch (err) {
            return { passOK: false, errors }
        }
    }

如何将其作为中间件传递?

代码语言:javascript
复制
export default ({ app }:{app:Application}) => {
    app.use(ExpressError)
}

传递错误状态

代码语言:javascript
复制
const { passOK, errors } = passwordUtils.passwordRegex({
                props: req.body,
                fields: [
                    { fieldName: "firstName", name: "First name" },
                    { fieldName: "lastName", name: "Last name" },
                    { fieldName: "email", name: "Email" },
                ],
            })

            if (!passOK) {
                return next(new ErrorResponse(errors, 400))
            }

希望这有助于回答您的问题,以自定义您的错误,我刚才给出了一个概述,但您可以继续检查错误的确切代码和值,以确定错误类型,并返回适当的错误消息或日志。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71630674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档