简体   繁体   中英

GraphQL Spring Boot Web Interceptor to return an error response if headers not present

I'm trying to create logic that will intercept all /graphql requests, check if headers are present and add them to MDC, and if not "reject" the request with an appropriate error.

First attempt was to add it to a registered AsyncHandlerInterceptor#preHandle , where I threw an IllegalArgumentException . Unfortunately, the DataFetcherExceptionResolverAdapter does not pick it up. Then I tried aa WebInterceptor , but again the resolver doesn't see this exception.

Here is the interceptor, I'm very new to reactive, so pls don't judge lol. It seems to work correctly, when the header is present, but not when the exception is thrown.

@Bean
public WebInterceptor headerInterceptor() {
    return (webInput, chain) ->
        chain.next(webInput)
            .doFirst(() -> {
                String header = webInput.getHeaders().getFirst("some-header");
                if (header != null && !header.isEmpty()) {
                    MDC.put("some-header", header);
                } else throw new IllegalArgumentException("...");
            })
            .doFinally(s -> MDC.clear());
}

Interceptor code (not reached):

public class SomeDataFetcherExceptionResolverAdapter extends DataFetcherExceptionResolverAdapter {

    @Override
    protected GraphQLError resolveToSingleError(Throwable throwable, DataFetchingEnvironment environment) {
        if (throwable instanceof ConstraintViolationException || throwable instanceof IllegalArgumentException) {
            return GraphqlErrorBuilder
                    .newError(environment)
                    .errorType(BAD_REQUEST)
                    .message(throwable.getMessage())
                    .build();
        } else {
            return super.resolveToSingleError(throwable, environment);
        }
    }
}

Add @ControllerAdvice

This worked for me

Here's what I ended up doing:

public class GraphqlHeaderInterceptor implements WebInterceptor {
...
    @Override
    public Mono<WebOutput> intercept(WebInput input, WebInterceptorChain chain) {
        return chain.next(input)
                .doFirst(() -> {
                     // fill MDC or throw Exception if no header
                })
                .onErrorResume(ex -> Mono.just(errResult(input, ex)))
                .doFinally(s -> MDC.clear());
    }

    private WebOutput errResult(WebInput input, Throwable ex) {
        var error = GraphqlErrorBuilder
            .newError()
            .errorType(BAD_REQUEST)
            .message(ex.getMessage())
            .build();

        var result = ExecutionResultImpl.newExecutionResult().addError(error).build();
        return new WebOutput(input, result);
    }
...
}

Which is good enough for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM