Issue
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 a a 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);
}
}
}
Solution
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.
Answered By - dpozinen
Answer Checked By - Senaida (JavaFixing Volunteer)