如何为Spring GraphQL 1.0.1创建自定义Instrumentation以限制单次API调用的查询数量
自定义Instrumentation限制单次请求的查询数量
当然可以实现!你完全可以仿照现有的MaxQueryComplexityInstrumentation和MaxQueryDepthInstrumentation,自定义一个Instrumentation来限制单次请求中包含的操作(查询、变更等)数量。下面是具体的实现步骤:
1. 编写自定义Instrumentation类
我们继承SimpleInstrumentation,重写beginParse方法,在请求解析完成后统计操作数量,超过阈值就抛出错误。这里的“操作”默认包含query、mutation和subscription,如果你只想限制query类型,可以额外添加过滤条件。
import graphql.ExecutionInput; import graphql.ParseResult; import graphql.language.Document; import graphql.language.OperationDefinition; import graphql.schema.instrumentation.SimpleInstrumentation; import graphql.schema.instrumentation.SimpleInstrumentationContext; import java.util.List; public class MaxQueryCountInstrumentation extends SimpleInstrumentation { private final int maxQueryCount; // 构造函数传入阈值 public MaxQueryCountInstrumentation(int maxQueryCount) { this.maxQueryCount = maxQueryCount; } @Override public SimpleInstrumentationContext<ParseResult> beginParse(ExecutionInput executionInput, InstrumentationState state) { // 解析完成后触发回调逻辑 return SimpleInstrumentationContext.whenCompleted((parseResult, throwable) -> { if (throwable == null && parseResult.isPresent()) { Document document = parseResult.get().getDocument(); // 获取请求中的所有操作定义 List<OperationDefinition> operations = document.getDefinitionsOfType(OperationDefinition.class); // 如果只想限制query类型,可添加过滤逻辑: // long queryCount = operations.stream() // .filter(op -> op.getOperationType() == OperationDefinition.OperationType.QUERY) // .count(); int operationCount = operations.size(); if (operationCount > maxQueryCount) { // 抛出自定义GraphQL错误,返回标准错误格式给客户端 throw new TooManyOperationsError(String.format( "单次请求最多允许%d个操作,当前提交了%d个", maxQueryCount, operationCount )); } } }); } }
2. 自定义GraphQL错误类(可选但推荐)
为了让客户端收到标准的GraphQL错误响应(而非通用的500错误),我们可以自定义一个实现GraphQLError的错误类:
import graphql.ErrorClassification; import graphql.GraphQLError; import graphql.language.SourceLocation; import java.util.List; public class TooManyOperationsError implements GraphQLError { private final String message; public TooManyOperationsError(String message) { this.message = message; } @Override public String getMessage() { return message; } @Override public List<SourceLocation> getLocations() { return null; } @Override public ErrorClassification getErrorType() { // 标记为验证错误,符合GraphQL规范 return ErrorClassification.ValidationError; } }
3. 配置Instrumentation Bean
和你现有的复杂度、深度配置保持一致,添加对应的Bean定义:
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.beans.factory.annotation.Value; @Configuration public class GraphQLInstrumentationConfig { // 你的现有配置:maxQueryComplexity和maxQueryDepth的Bean... @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "spring.graphql.instrumentation", name = "max-query-count") public MaxQueryCountInstrumentation maxQueryCountInstrumentation( @Value("${spring.graphql.instrumentation.max-query-count}") int maxQueryCount) { return new MaxQueryCountInstrumentation(maxQueryCount); } }
4. 配置阈值参数
在application.properties或application.yml中添加配置:
# 限制单次请求最多5个操作 spring.graphql.instrumentation.max-query-count=5
这样配置完成后,当用户提交的请求中操作数量超过你设置的阈值时,服务器会返回标准的GraphQL错误响应,拒绝该请求,从而达到保护服务器的目的。
内容的提问来源于stack exchange,提问作者rubalvjaiswal
相关产品推荐
相关产品推荐

