简体   繁体   中英

How to set header variables in GraphQL-SPQR

I'm running a GraphQL API using GraphQL-SPQR and Spring Boot.

At the moment, I am throwing RuntimeException s to return GraphQL errors. I have a customExceptionHandler that implements DataFetcherExceptionHandler that returns errors in the correct format, as shown below:

class CustomExceptionHandler : DataFetcherExceptionHandler {
    override fun onException(handlerParameters: DataFetcherExceptionHandlerParameters?): DataFetcherExceptionHandlerResult {


        // get exception
        var exception = handlerParameters?.exception
        val locations = listOf(handlerParameters?.sourceLocation)
        val path = listOf(handlerParameters?.path?.segmentName)

        // create a GraphQLError from your exception
        if (exception !is GraphQLError) {
            exception = CustomGraphQLError(exception?.localizedMessage, locations, path)
        }

        // cast to GraphQLError
        exception as CustomGraphQLError

        exception.locations = locations
        exception.path = path

        val errors = listOf<GraphQLError>(exception)

        return DataFetcherExceptionHandlerResult.Builder().errors(errors).build()
    }
}

I use the CustomExceptionHandler as follows (in my main application class):

@Bean
    fun graphQL(schema: GraphQLSchema): GraphQL {
        return GraphQL.newGraphQL(schema)
                .queryExecutionStrategy(AsyncExecutionStrategy(CustomExceptionHandler()))
                .mutationExecutionStrategy(AsyncSerialExecutionStrategy(CustomExceptionHandler()))
                .build()
    }

I'd like to set a header variable for a UUID that corresponds to the exception, for logging purposes. How would I do that?

Even better, is it possible to create a Spring Bean that puts the UUID in the header for all queries and mutations?

Thanks!

when you're using spring boot, there's two options:

  • you're using the spring boot graphql spqr starter (which brings it's own controller to handle all graphQL requests)
  • you're using plain graphql-spqr and have your own controller to handle GraphQL requests

In any case, you've got a few options:

Making your CustomExceptionHandler a Spring Bean and Autowiring HttpServletResponse

That would probably be the easiest way to go - and it would probably work in any case: You could simply make your CustomExceptionHandler a Spring bean and have it autowire the HttpServletRequest - in the handler method, you could then set it to whatever you would like it to be. Here's some dummy code in Java (sorry, I am not proficient enough in Kotlin):

@Component
class CustomExceptionHandler implements DataFetcherExceptionHandler {
    private final HttpServletResponse response; 

    public CustomExceptionHandler(HttpServletResponse response) {
        this.response = response; 
    }

    @Override
    public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) {
        response.setHeader("X-Request-ID", UUID.randomUUID().toString());
        // ... your actual error handling code
    }
}

This is going to work because spring will realise that HttpServletRequest differs for each request. It will therefore inject a dynamic proxy into your error handler that will point to the actual HttpServletResponse instance for every request.

I would argue, that it's not the most elegant way, but it will certainly solve your problem.

for the graphql-spqr spring boot starter

There's a default controller implementation that is used in projects using this starter. That controller will handle every graphql request that you receive. You can customise it, by implementing your own GraphQLExecutor and making it a spring bean. That executor is responsible to call the GraphQL engine, pass the parameters in and output the response. Here's the default implementation , that you might want to base your work on.

Similarly to the previous solution, you could autowire the HttpServletResponse in that class and set a HTTP Response header.

That solution would allow you to decide, if you want to set a request id in all cases, or just in specific error cases. ( graphql.execute returns an object from which you can get the information if and what errors existed)

when using graphql-spqr without the spring boot starter

Locate your GraphQL controller, add an argument to that method of type HttpServletRequest - and then add headers to that as you prefer (see previous section on some more specific suggestions)

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