graphqlspring-webfluxrequest-headersspring-boot-3java-21

Java 21 with Spring Boot 3.2 and WebFlux unable to get Headers from GraphQL request


I am using Java 21 with Spring Boot 3.2 and WebFlux. I need to receive some of my requests using GraphQL. I have the base project working, and am able to call my Controller/Service classes. However, I want to get the JWT from the request, but I am unable to get that working. If I add ServerHttpRequest request to the Controller parameters, I get the following error:

"message": "[IllegalStateException]: Parameter [0] in public java.util.Collection<com.myapp.rtf.model.Customer> com.myapp.rtf.controller.CustomerController.queryCustomers(org.springframework.http.server.ServerHttpRequest,java.lang.String):  was not recognized by any resolver and there is no source/parent either. Please, refer to the documentation for the full list of supported parameters.",

If I remove the ServerHttpRequest request from the controller, then my request works fine, but I am unable to get the request headers. Here are relevant files:

schema.graphqls

type Customer {
    firstName: String
    lastName: String
    zipCode: String
    address: String
    email: String
}

type Query {
    queryCustomers(zipCode: String): [Customer]
}

schema {
    query: Query
}

Controller

import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.stereotype.Controller;

import java.util.Collection;

@Controller
public class CustomerController {

    private final CustomerService service;

    public CustomerController(CustomerService service) {
        this.service = service;
    }

    @QueryMapping
    public Collection<Customer> queryCustomers(ServerHttpRequest request, @Argument String zipCode) {
        return service.queryCustomers(zipCode);
    }

}

That gives the error. If I try to Autowire or pass in the ServerHttpRequest to the constructor, such as:

public CustomerController(ServerHttpRequest request, CustomerService service) {

I get the following error:

Parameter 0 of constructor in com.myapp.rtf.controller.CustomerController required a bean of type 'org.springframework.http.server.ServerHttpRequest' that could not be found.

How do I get the headers from requests with this WebFlux setup? I also tried using ServerWebExchange, but getting the same errors. Thanks


Solution

  • From the Spring GraphQL documentation, if you want to read headers in controllers, you can use a WebGraphQlInterceptor to read it from Http request firstly, and transport to GraphQLContext.

    class RequestHeaderInterceptor implements WebGraphQlInterceptor { 
    
        @Override
        public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
            String value = request.getHeaders().getFirst("Bearer");
            request.configureExecutionInput((executionInput, builder) ->
                    builder.graphQLContext(Collections.singletonMap("token", value)).build());
            return chain.next(request);
        }
    }
    
    @Controller
    class CustomerController { 
    
        @QueryMapping
        Flux<Customer> queryCustomers(@ContextValue String token, @Argument String zipCode) {
            ...
        }
    }