I'm using graphql-java 20.0 (in spring-boot-starter-graphql in Kotlin) and want to add custom headers to my resolver's responses. Currently, my resolvers return just the entity (of type MyEntity
) that should be included in the graphql response - which works:
@QueryMapping
fun myResolver(
@Argument arg1: String,
@Argument arg2: MyInput,
): MyEntity = service.getMyEntity(arg1, arg2)
I tried changing this to a ResponseEntity as recommended in this SO answer but that's apparently not handled by graphql-java and results in my responses' data being null:
/* this does not work, since graphql-java doe not map the ResponseEntity's body
and results in a graphql response with null in the data object */
@QueryMapping
fun myResolver(
@Argument arg1: String,
@Argument arg2: MyInput,
): ResponseEntity<MyEntity> = ResponseEntity.ok().run {
this.header("X-My-Header", "whatever")
}.body(service.getMyEntity(arg1, arg2))
I could not, however, find any alternative that allows me to set custom headers alongside my response. On StackOverflow, I only found answers for Laravel and Astro. On the graphql-spring-boot repo there's a similar question left unanswered since almost two years.
Does anyone know of a way to set custom headers in my graphql resolvers? I need to do this because my headers need to be different based on some request properties.
After upgrading dependencies my other answer no longer works. Thankfully, I found a cleaner solution:
This answer works with the following dependency tree (GraphQl-relevant parts):
based on Spring GraphQL / Server Transports / Interception
QueryMapping
s can receive a GraphQLContext
and set values on it.WebGraphQlInterceptor
s can retrieve the values from GraphQLContext
and modify the response (headers)The resolver gets a graphql.GraphQLContext
(automatically injected):
@QueryMapping
fun myResolver(
@Argument arg1: String,
@Argument arg2: MyInput,
context: GraphQLContext,
): MyEntity = service.getMyEntity(arg1, arg2).also {
context.put("my-value", "whatever inferred from ${it}")
}
And a org.springframework.graphql.server.WebGraphQlInterceptor
retrieves the value from GraphQLContext
and modifies the response (headers):
import org.springframework.graphql.server.WebGraphQlInterceptor
import org.springframework.graphql.server.WebGraphQlRequest
import org.springframework.graphql.server.WebGraphQlResponse
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
@Component
class GraphQLHeaderInterceptor : WebGraphQlInterceptor {
override fun intercept(request: WebGraphQlRequest, chain: WebGraphQlInterceptor.Chain): Mono<WebGraphQlResponse> {
return chain.next(request).doOnNext { response: WebGraphQlResponse ->
val value = response.executionInput.graphQLContext.get<String>("my-value")
response.responseHeaders.set("X-My-Header", value ?: "default value")
}
}
}