graphql-client
graphql-client copied to clipboard
Adding Custom Header to GraphQLHttpClient
Hi there:
I have got a GraphQL Client instance which is tying to call a GraphQL API endpoint. My code looks like below:
`var graphQLClient = new GraphQLHttpClient("https://abc.com/graphql", new NewtonsoftJsonSerializer());
var raceRequest = new GraphQLRequest { Query = @" query ($input: GetRaceResultsInput, $before: String, $after: String, $first: Int, $last: Int) { getRaceResults(before: $before, after: $after, first: $first, last: $last, input: $input) { edges { cursor node { raceId horses { horseId } } } } }" };
var graphQLResponse = await graphQLClient.SendQueryAsync<RaceResult>(raceRequest);`
RaceResult is of the format: public class RaceResult { public string Result { get; set; } }
When the SendQueryAsync is excuted, I get the following error:
System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. System.ComponentModel.Win32Exception (0x80090326): The message received was unexpected or badly formatted.
My request header in postman has got custom key value pair like x-developer-secret and I get the desired result. Is there anyway to add customer header before calling the API? I tried the following:
graphQLClient.HttpClient.DefaultRequestHeaders.Add("Authorization", $"bearer abcsecret");
However it didn't work. Any help would be appreciated.
Thanks
Well... you added an Authorization
header... But I suppose you'd need to add a x-developer-secret
header instead?
In his example, aschattopadhyay added Authorization
to whole HttpClient:
Please note that maybe this is not what you want:
This solution (adding to HttpClient.DefaultRequestHeaders
) is heavily dependent on how you get yout HttpClient
instance and what you want to do:
- This works when you have HttpClient as "transient" but thats bad idea because Socket Exhaustion
- This is ok when you are doing queries only on behalf of one specific user (ie you have ApiKey or DeviceKey and are sending requests to (lets say) google calendar as app).
- This is broken when you have long-living HttpClient (ie HttpClientFactory or GraphQLHttpClient as singleton) and you are doing request on behalf of multiple users (not in single request of course, for example one microservice calling other & setting user becouse of role management: multiple requests will race which Authorization is really send. May work at 99% of cases, i dont know)
(My use case is point 3)
I think (i am not collaborator, i just goes and looks in source code because there AFAIK isnt any documentation) the right solution is extend and override HttpRequestMessage ToHttpRequestMessage
something like
public class GraphQLHttpRequestWithHeadersSupport : GraphQLHttpRequest
{
public override HttpRequestMessage ToHttpRequestMessage(GraphQLHttpClientOptions options, IGraphQLJsonSerializer serializer)
{
var r = base.ToHttpRequestMessage(options, serializer);
r.Headers = SET YOUR REQUEST SPECIFIC HEADERS
}
}
var graphQLClient = new GraphQLHttpClient("https://abc.com/graphql", new NewtonsoftJsonSerializer());
var raceRequest = new GraphQLHttpRequestWithHeadersSupport {Query = @"your query"};
var graphQLResponse = await graphQLClient.SendQueryAsync(raceRequest);
This HttpRequestMessage
is used in client.SendAsyn()
so you are not setting DefaultRequestHeaders
and everything should work.
Pretty much #330
something like
public class GraphQLHttpRequestWithHeadersSupport : GraphQLHttpRequest ...
This
HttpRequestMessage
is used inclient.SendAsyn()
so you are not settingDefaultRequestHeaders
and everything should work.
Good suggestion. I ended up making the Authorization Header customizable.
public class GraphQLHttpRequestWithAuthSupport : GraphQLHttpRequest {
public AuthenticationHeaderValue? Authentication { get; set; }
public override HttpRequestMessage ToHttpRequestMessage(GraphQLHttpClientOptions options, IGraphQLJsonSerializer serializer) {
var r = base.ToHttpRequestMessage(options, serializer);
r.Headers.Authorization = Authentication;
return r;
}
}
Usage:
var getTokenRequest = new GraphQLHttpRequestWithAuthSupport {
Query = @"{ myQuery }",
Authentication = new AuthenticationHeaderValue(@"Bearer", @"xyz")
};
Should really be part of the doc, it's very difficult to guess that just to add a JWT in Authorization for ex