spring-projects / spring-graphql

Spring Integration for GraphQL
https://spring.io/projects/spring-graphql
Apache License 2.0
1.54k stars 306 forks source link

How to provide context to response in WebGraphQlInterceptor? #1063

Open hameno opened 1 month ago

hameno commented 1 month ago

We need to access some contextual data about the executed GraphQL query in a HttpFilter. I tried to make use of Context Propagation using a ThreadLocal but it does not seem to be written to (only read).

What am I missing?

Example:

WebGraphQlInterceptor { request, chain ->
        chain.next(request).flatMap { response -> 
            Mono.just(response).contextWrite(Context.of("TEST", "value from response"))
        }
    }
bclozel commented 1 month ago

I'm not sure I entirely understand the use case here.

Where does the value come from and what is this value representing? Where this value should be read? Are you expecting this value to be present in the reactor context, graphql context, somewhere else?

hameno commented 1 month ago

I have a request metering middleware that uses a HttpFilter to perform its task. I need to enrich the data with tenant information that gets calculated during the GraphQL execution. I want to make this tenant data available to the HttpFilter

bclozel commented 1 month ago

After discussing this with @rstoyanchev , I have decided to remove my previous comment as it was misleading. Manually setting a ThreadLocal from a controller and expecting the value to be accessible in a filter would not work reliably and would create lifecycle issues.

I'm reopening this issue to discuss this more thoroughly and consider different options.

First, we had several questions about tenant ids and how to propagate that information. But usually this happens "top to bottom", as the information is extracted at the protocol at the same time as authentication is performed. In that mode, you can use context propagation and the graphql context. Could you explain things a bit more here? I would really like to better understand where this tenant information is coming from and how can you rely on that information being present if it depends on the query sent by the client. Maybe you could show us some code snippets and explain in details this requirement for your application.

Now propagating an information "bottom to top" is not straightforward and basically calls for some type of mutable map that any data fetcher can put information into. We could use HTTP request attributes for that, although this information might be not accessible from the interceptor contract we're providing now. This information is probably not confidential and might be available anyway in the execution result, which is available. You could even consider putting it in the extensions response map.

Thanks!