You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在@inversifyjs/http-express中规范实现NotFound(404)API路由

如何在@inversifyjs/http-express中规范实现NotFound(404)API路由

我之前用@inversifyjs/http-express搭API的时候也卡过这个404路由的问题,官方文档这块确实没给明确指引,后来折腾了一阵,发现其实可以利用Express的原生特性优雅解决,刚好和你现在的思路对上,给你梳理下更规范的实现方式:

因为@inversifyjs/http-express本质是Express的封装,所以我们完全可以沿用Express的中间件优先级逻辑——把404中间件放在所有路由注册完成之后,这样所有匹配不到已定义接口的请求,都会自动走到这个中间件里。

基础实现方案(和你的思路一致,优化细节)

这种方式简单直接,不需要依赖额外的DI注入,适合大多数场景:

import { Container } from 'inversify';
import { InversifyExpressHttpAdapter } from '@inversifyjs/http-express';
import { Request, Response } from 'express';
import { HttpStatusCode } from '你的状态码枚举路径';

// 假设你已经实现了这些全局中间件和过滤器
import CorsMiddleware from './middlewares/cors';
import HelmetMiddleware from './middlewares/helmet';
import RateLimitMiddleware from './middlewares/rate-limit';
import CookieParserMiddleware from './middlewares/cookie-parser';
import LoggerMiddleware from './middlewares/logger';
import GlobalErrorFilter from './filters/global-error';

export class Server {
  private adapter: InversifyExpressHttpAdapter;

  constructor(private readonly container: Container) {
    this.adapter = new InversifyExpressHttpAdapter(this.container, {
      useJson: true,
    });

    // 先注册所有全局中间件
    this.adapter.applyGlobalMiddleware(CorsMiddleware);
    this.adapter.applyGlobalMiddleware(HelmetMiddleware);
    this.adapter.applyGlobalMiddleware(RateLimitMiddleware);
    this.adapter.applyGlobalMiddleware(CookieParserMiddleware);
    this.adapter.applyGlobalMiddleware(LoggerMiddleware);

    // 注册全局错误过滤器
    this.adapter.useGlobalFilters(GlobalErrorFilter);
  }

  public async getApp() {
    // 关键:先让Inversify构建所有已注册的控制器路由
    const app = await this.adapter.build();
    // 再挂载404中间件,确保它是最后一个被执行的中间件
    app.use(notFoundMiddleware);
    return app;
  }
}

// 独立的404中间件,返回标准化的错误响应
function notFoundMiddleware(req: Request, res: Response) {
  return res.status(HttpStatusCode.NOT_FOUND).json({
    statusCode: HttpStatusCode.NOT_FOUND,
    message: `Route '${req.originalUrl}' not found`,
    data: null,
  });
}

进阶:把404中间件纳入DI容器管理

如果你的404处理需要依赖容器中的其他服务(比如自定义的错误日志服务),可以把中间件改成可注入的类:

import { injectable } from 'inversify';
import { Request, Response } from 'express';
import { HttpStatusCode } from '你的状态码枚举路径';

// 用@injectable()装饰,让它能被Inversify容器管理
@injectable()
export class NotFoundMiddleware {
  // 如果需要依赖其他服务,直接在构造函数注入即可
  constructor() {}

  handle(req: Request, res: Response) {
    return res.status(HttpStatusCode.NOT_FOUND).json({
      statusCode: HttpStatusCode.NOT_FOUND,
      message: `Route '${req.originalUrl}' not found`,
      data: null,
    });
  }
}

// 然后在Server类中调整:
public async getApp() {
  const app = await this.adapter.build();
  // 从容器中获取中间件实例
  const notFoundMiddleware = this.container.get<NotFoundMiddleware>(NotFoundMiddleware);
  // 绑定this上下文后挂载
  app.use(notFoundMiddleware.handle.bind(notFoundMiddleware));
  return app;
}

核心注意点

  • 一定要在adapter.build()之后挂载404中间件:因为build()方法会把所有通过@controller装饰器注册的路由都绑定到Express实例上,中间件是按注册顺序执行的,放在最后才能确保所有未匹配的请求都被捕获。
  • 不需要纠结Inversify有没有内置的404处理:官方确实没做这个封装,因为底层Express已经提供了完善的中间件机制,直接用就好,这也是社区里的通用做法。

火山引擎 最新活动