For everyone who is looking for a up-to-date solution (in 2024): The spring-for-graphql framework is providing a graphql-request-interceptor. We can use such an interceptor to put all the request headers into the graphql-context.
/**
* Interceptor that extracts headers from the request and adds them to the GraphQL context.
* This allows you to access them in your GraphQL resolvers via '@ContextValue'.
*/
@Component
class GraphQlRequestHeaderInterceptor(
private val log: KLogger = KotlinLogging.logger {}
) : WebGraphQlInterceptor {
override fun intercept(request: WebGraphQlRequest, chain: Chain): Mono<WebGraphQlResponse> {
val headers = getHeadersFromRequest(request)
log.trace { "Found ${headers.size} headers that will be added to the GQL-context: $headers" }
addHeadersToGraphQLContext(request, headers)
return chain.next(request)
}
private fun getHeadersFromRequest(request: WebGraphQlRequest): Map<String, Any> {
return request.headers.mapValues { it.value.first() }
}
private fun addHeadersToGraphQLContext(
request: WebGraphQlRequest, customHeaders: Map<String, Any>
) = request.configureExecutionInput { _, builder ->
builder.graphQLContext(customHeaders).build()
}
}
After that, we can access the headers by marking method-parameters in our resolvers with @ContextValue
. You can find a full solution on Medium & GitHub:
@Controller
class AddTaskController(private val useCase: AddTaskUseCase) {
private val log = KotlinLogging.logger {}
@MutationMapping
fun addTask(
@Argument payload: TaskInput,
@ContextValue(X_USER_ID) userId: String
): TaskDto {
log.debug { "Received graphql-request to add task: $payload" }
val command = payload.toAddTaskCommand(userId)
val task = useCase.addTask(command)
return TaskDto.from(task)
}
}