【问题标题】:Applying middleware in Nestjs. Or what is proper use of swagger-ui-express packages in Nestjs?在 Nestjs 中应用中间件。或者在 Nestjs 中正确使用 swagger-ui-express 包是什么?
【发布时间】:2019-10-22 03:47:29
【问题描述】:

我有 API 在路径 /API 上侦听。 (代码暂时在这里https://github.com/vit100/nest-middleware-test

有中间件(提供静态 swagger 文件)为 root 申请,如下所示:

// app.module.ts------------
import { F1, F2, F3 } from './swaggerMiddleware';

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer): void | MiddlewareConsumer {
  consumer.apply(F1, F2, F3).exclude('/api').forRoutes('/');
  }
}
// end of app.module.ts------------

//swaggerMiddleware.ts-------------------------

import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { Request, Response } from 'express';
import yamljs from 'yamljs';
import swaggerUiExpress from 'swagger-ui-express';

const yamlDoc = yamljs.load(__dirname + '\\swagger.yaml');

@Injectable()
export class F1 implements NestMiddleware {
  use(req: Request, res: Response, next: () => void) {
    if (req.url.includes('api')) {
      return next();
    }
    req.url = req.originalUrl;
    return swaggerUiExpress.serve[0].call(this, req, res, next);
  }
}


@Injectable()
export class F2 implements NestMiddleware {
  use(req: Request, res: Response, next: () => void) {
    if (req.url.includes('api')) {
      return next();
    }
    req.url = req.originalUrl;
    return swaggerUiExpress.serve[1].call(this, req, res, next);
  }
}


@Injectable()
export class F3 implements NestMiddleware {
  use(req: Request, res: Response, next: () => void) {
    if (req.url.includes('api')) {
      return next();
    }
    req.url = req.originalUrl;
    return swaggerUiExpress.setup(yamlDoc).call(this, req, res, next);
  }
}
//end of swaggerMiddleware.ts-------------------------

我没有找到其他集成 swaggerUiExpress 的方法。不幸的是,我必须将调用拆分为单独的中间件类。 类,而不是函数——因为.exclude('/api') 不适用于函数中间件。还必须重新分配req.url = req.originalUrl;,因为它在某处丢失了......

它开始工作了,但我不知道。对我来说,这很鱼腥... 或者应该是另一种服务这种逻辑的方式,比如这个 swagger 中间件?

【问题讨论】:

  • 这种官方方式你试过了吗? github.com/scottie1984/swagger-ui-express 你确定你可以在同一个req,res,next 对象上调用两个中间件,即servesetup?我认为您必须像这样链接app.use('/', swaggerUi.serve, swaggerUi.setup(yamlDoc));
  • 是的,我做到了——效果很好。但是我需要提供由另一种方式支持/生成的外部文件,并且该文件在其他应用程序之间共享。这就是我尝试使用这种方式的原因。
  • 是的,这看起来很可疑。

标签: swagger nestjs


【解决方案1】:

无论您的用例如何,我都认为这不是一个好方法。您在每个请求上加载一个 yaml 文件,它超出范围,收集垃圾并从文件系统重新读取下一个请求。您应该在请求之外加载文件并从内存中提供它。 编辑:如果需要根据更改刷新文件,可以使用fs.watch

至于为什么这不起作用,您在同一个 reqresnext 对象上调用了两个不同的中间件。但是当您在第一个中间件上调用 next 时,它会移交给框架链接并在 next 中引用的下一个中间件。当您的第二个中间件调用next 时,框架已经开始写入响应,因为请求-响应周期已经结束。您需要做的是通过将第二个中间件作为第一个中间件的下一个处理程序传递来自己链接这些中间件。像这样,

import swaggerUiExpress from 'swagger-ui-express';
import yamljs from 'yamljs';
const yamlDoc = yamljs.load(__dirname + '\\swagger.yaml');

export function swaggerMiddleware(req, res, next) {
 swaggerUiExpress.serve[0](req, res, function (req, res) {
     swaggerUiExpress.setup(yamlDoc)(req, res, next)
 });
);
}

【讨论】:

  • 是和不是。是的 - 我需要在下一个位置调用第二个中间件是正确的。原问题已更正。不 - 它还有另一个问题。我相信与nestjs的处理方式有关
猜你喜欢
  • 2019-09-16
  • 2020-09-12
  • 1970-01-01
  • 2022-08-19
  • 2021-12-07
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 2019-05-25
相关资源
最近更新 更多