【问题标题】:NestJS - request timeoutNestJS - 请求超时
【发布时间】:2018-08-17 16:21:01
【问题描述】:

如何为所有请求设置超时,如果超时则使用自定义 json 响应?

我尝试使用:

import * as timeout from 'connect-timeout';

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';

const port = process.env.PORT || 3020;

async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  app.use(timeout('5s'));
  app.use(haltOnTimedOut);

  await app.listen(port);
} 
bootstrap();


function haltOnTimedOut (req, res, next) {
  if (!req.timedout){
      next();
  } else {
      res
        .status(408)
        .json({ status: 'error', data: 'timeout'})
  }
}

但没有运气。

【问题讨论】:

    标签: express nestjs


    【解决方案1】:

    为了增加 nestjs - API 应用服务器请求/响应超时,我在 main.js 中做了以下操作

    const server = await app.listen(5000);
    server.setTimeout(1800000); // 600,000=> 10Min, 1200,000=>20Min, 1800,000=>30Min
    

    【讨论】:

    • 谢谢!解决了我的问题!你也可以这样做:server.setTimeout(30 * 60 * 1000);
    【解决方案2】:

    NestJS 有一个称为拦截器的功能。拦截器可用于强制超时,他们在这里演示,TimeoutInterceptor

    假设您将拦截器放在一个名为 timeout.interceptor.ts 的文件中:

    import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from '@nestjs/common';
    import { Observable, throwError, TimeoutError } from 'rxjs';
    import { catchError, timeout } from 'rxjs/operators';
    
    @Injectable()
    export class TimeoutInterceptor implements NestInterceptor {
      intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        return next.handle().pipe(
          timeout(5000),
          catchError(err => {
            if (err instanceof TimeoutError) {
              return throwError(new RequestTimeoutException());
            }
            return throwError(err);
          }),
        );
      };
    };
    

    在此之后,您必须注册它,这可以通过多种方式完成。全局注册方式如下图:

    const app = await NestFactory.create(AppModule);
    app.useGlobalInterceptors(new TimeoutInterceptor());
    

    【讨论】:

    • 这种方法的问题是很多代码可以在拦截器之前运行(例如你的守卫或中间件),你仍然希望你的超时适用于那些。
    【解决方案3】:

    您可以将 express 实例传递给 NextFactory.create(module, expressInstance),这样您就可以将中间件添加到该 express 实例中,例如

    const expressInstance = express();
    express.use(timeout('4'));
    express.use((err, res, req, next) => req.jsonp(err)); // DON'T USE FOR PRODUCTION
    const app = NestFactory.create(AppModule, express);
    

    它应该可以工作。

    【讨论】:

    • 即使我的解决方案超时有效,但我无法将默认响应从 html 更改为我提供的 json。
    • github.com/expressjs/timeout/blob/master/index.js#L82 如果您检查此代码,则会将错误返回到由错误处理程序处理的中间件。您可以编写这样的函数(err, res, req, next) =&gt; { req.jsonp(err) },以便解决。注意:不要在生产中使用这个使用你自己的错误处理程序
    【解决方案4】:

    app.use(timeout('5s')); 移出bootstrap 函数,并同时从haltOnTimedOut 函数中删除else 块。

    并尝试将您的 bootstrap 函数作为中间件调用,如下所示,

    app.use(boostrap, timeout('5s'), bodyParser.json(), haltOnTimedout, function (req, res, next) {
    if (req.timedout) return
          res
            .status(408)
            .json({ status: 'error', data: 'timeout'})
    });
    

    希望这会有所帮助!

    【讨论】:

    • 如果应用程序在引导函数中定义,应用程序如何使用引导程序?
    猜你喜欢
    • 2020-05-28
    • 2011-02-26
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 2016-05-27
    • 2020-05-31
    相关资源
    最近更新 更多