You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS/GraphQL中拦截Apollo标准HTTP错误?

在NestJS/GraphQL中拦截或修改Apollo的标准HTTP错误

这个问题我之前踩过坑!其实核心原因是你遇到的HttpQueryError(比如"GET query missing")和常规GraphQL错误不在同一个处理阶段,所以常规的GraphQL异常过滤器根本碰不到它。

为什么常规GraphQL过滤器拦截不到?

你平时用的GraphQL异常过滤器,作用是拦截GraphQL执行阶段(比如Resolver里抛出的异常、Schema验证错误等)的错误。而HttpQueryError是Apollo Server在还没进入GraphQL请求处理流程时就抛出的——比如当你用GET请求访问GraphQL端点(且没有符合要求的查询参数),Apollo会直接在HTTP层面拒绝请求,还没走到GraphQL的执行逻辑,自然不会被GraphQL过滤器捕获。

具体解决方案

下面给你三种可行的实现方式,按需选择:

1. 使用Nest全局HTTP异常过滤器

因为这类错误本质是HTTP级别的异常,所以可以用Nest的全局HTTP异常过滤器来捕获并修改响应:

首先创建全局过滤器:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Response } from 'express';

@Catch()
export class GlobalHttpExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    // 识别Apollo的HttpQueryError
    if (exception.name === 'HttpQueryError') {
      return response.status(exception.statusCode).json({
        statusCode: exception.statusCode,
        message: '请使用POST请求访问GraphQL接口,并携带正确的查询参数',
        error: exception.message,
      });
    }

    // 处理其他HTTP异常
    if (exception instanceof HttpException) {
      const status = exception.getStatus();
      return response.status(status).json(exception.getResponse());
    }

    // 兜底处理未知错误
    response.status(500).json({
      statusCode: 500,
      message: '服务器内部错误',
    });
  }
}

然后在main.ts中注册全局过滤器:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 注册全局HTTP异常过滤器
  app.useGlobalFilters(new GlobalHttpExceptionFilter());
  await app.listen(8080);
}
bootstrap();

2. 自定义Apollo Server插件

Apollo允许通过插件介入请求的生命周期,包括捕获前置的HTTP错误:

创建Apollo插件:

import { ApolloServerPlugin, GraphQLRequestContext } from '@apollo/server';

export class ApolloHttpErrorInterceptorPlugin implements ApolloServerPlugin {
  async requestDidStart(requestContext: GraphQLRequestContext) {
    return {
      async didEncounterErrors(requestContext) {
        // 查找是否存在HttpQueryError
        const httpError = requestContext.errors?.find(
          err => err.extensions?.exception?.name === 'HttpQueryError'
        );

        if (httpError) {
          // 修改错误信息
          httpError.message = '自定义的GET请求错误提示';
          // 自定义响应状态码和内容
          requestContext.response?.http?.status = 400;
          requestContext.response?.http?.body = JSON.stringify({
            statusCode: 400,
            message: 'GraphQL接口仅支持POST请求,请检查请求方式',
          });
        }
      },
    };
  }
}

然后在GraphQL模块中配置插件:

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { ApolloHttpErrorInterceptorPlugin } from './apollo-http-error.plugin';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      playground: false,
      autoSchemaFile: true,
      // 注册自定义插件
      plugins: [new ApolloHttpErrorInterceptorPlugin()],
    }),
  ],
})
export class AppModule {}

3. 利用Apollo的formatError配置

如果你只需要修改错误的返回格式,也可以通过formatError来处理(注意:部分版本的Apollo可能需要确认是否能捕获到前置错误):

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  playground: false,
  autoSchemaFile: true,
  formatError: (error) => {
    // 识别HttpQueryError
    if (error.extensions?.exception?.name === 'HttpQueryError') {
      return {
        message: '自定义的请求错误信息',
        statusCode: error.extensions.exception.statusCode,
        extensions: {
          ...error.extensions,
          customInfo: '仅支持POST请求访问GraphQL端点',
        },
      };
    }
    // 其他GraphQL错误保持默认处理
    return error;
  },
})

内容的提问来源于stack exchange,提问作者Lewsmith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:42:34