Add a way to dynamically provide headers for clients
.. like maybe an SPI that allows to plug in a HeaderProvider that gets called before every request to provide the HTTP headers...?
Typesafe client can already get headers dynamically by using @Header(method="headerProviderMethod"), but this new feature could be supported for both client types.
There was already something like this in one of the first versions of the typesafe client. We removed it, as it can be difficult to understand where the header comes from.
True that it will be a bit confusing, but how else can we support dynamic header values...
Potentially client builders could accept a Function<SomeContext, String> that is called always when a header value is needed, SomeContext would be some kind of context that might be necessary to compute the value, but I'm not sure what exactly that context should contain (and maybe we don't need that context at all).
Hmmm... is there really a use-case to dynamically create header names? For dynamic values you can use the @Header(name = "Foo", method="myFooMethod") syntax.
No I'm not suggesting dynamic header names. The Function<SomeContext, String> would be assigned to a single header with a particular name, and only compute its value over time (that's the resulting String).
If you don't want to repeat the @Header(name = "foo", method = "MyClass.myMethod") on multiple APIs, you can extract this into a Stereotype. I think this is much cleaner that having some headers magically appear without any visible clue.
Yeah, but in this issue I'm focusing on how to enable this with dynamic clients (they don't have it at all), and these don't have any reasonable place where to put an annotation, that's why I'm suggesting something that can be passed to the client builder programmatically.
I needed custom per function headers (dynamically) with the dynamic client, so I had to roll out a custom client based on vertx as well to do it. Too bad smallrye client doesn't fit my needs
@riccardocossu, Does that mean that you need a different header depending on what operation is being invoked? We could quite easily add that - I'm mostly thinking what kind of context is necessary to pass to the header supplier, so possibly a JsonObject representing the whole GraphQL request would be the answer.
In which case, I would imagine adding this method to both TypesafeGraphQLClientBuilder and DynamicGraphQLClientBuilder:
header(String headerName, Function<JsonObject, String> headerValueSupplyingFunction);
Would that resolve your missing functionality?
@jmartisk thanks for your reply; I am using the client as a singleton, I plan to have just one of them around, or maybe a few. Certainly not one per request, so the builder doesn't seem to be a viable option.
What I need is to send custom headers whose name and value are dependent on what I get as input parameters; this may potentially vary on every request. What I did it's actually creating a new function:
public Uni<Response> executeAsync(String query, Map<String,Object> variables, Map<String, String> headers)
so that the caller decides which headers will be in the request, with complete control over them. I only need that for now, async execution of a query as string. That would a viable solution for me (I understand that it would have to be added to all the methods in that interface).
Certainly not one per request, so the builder doesn't seem to be a viable option.
Using the builder is not "one per request", you build a GraphQL client with the builder and then you can reuse it for many requests. Only the Function<JsonObject, String> would be called for each request.
But still, I see your point and I yeah I think adding variants of executeSync, executeAsync and subscription methods that take a headers parameter is probably more straightforward and more useful. These passed dynamic headers would be merged with headers passed via the builder (or static configuration). I'll look into implementing this.
Ok I see your point; both will works as long as every request is able to send whatever headers they please. Thanks for your help