I am using com.netflix.graphql.dgs:graphql-dgs-client:4.9.16
along with HttpClient (JDK 17)
I am creating graphql client using below.
GraphQLCLient graphQLClient = GraphQLClient.createCustom(
host-url,
requestExecutor::exec);
And my request executor is based on HttpClient and it’s implementation is roughly as below –
import com.netflix.graphql.dgs.client.HttpResponse;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Stream;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
public class RequestExecutor {
private final Supplier<String> bearer;
private final HttpClient httpClient;
public RequestExecutor(HttpClient httpClient) {
this(httpClient, null);
}
public RequestExecutor(HttpClient httpClient, Supplier<String> bearer) {
this.httpClient = httpClient;
this.bearer = bearer;
}
@SneakyThrows
public HttpResponse exec(
String url,
Map<String, ? extends List<String>> headers,
String body
) {
var requestBuilder = HttpRequest
.newBuilder(URI.create(url))
.headers(Util.flattenHeaders(headers))
.POST(BodyPublishers.ofString(body))
.version(Version.HTTP_1_1);
if (bearer != null) {
requestBuilder.header("Authorization", String.format("Bearer %s", bearer.get()));
}
var response = httpClient.send(
requestBuilder.build(),
java.net.http.HttpResponse.BodyHandlers.ofString()
);
return processResponse(body, response);
}
protected HttpResponse processResponse(String request, java.net.http.HttpResponse<String> response) {
return new HttpResponse(
response.statusCode(),
response.body(),
response.headers().map()
);
}
@NoArgsConstructor(access = AccessLevel.PRIVATE)
private static class Util {
public static String[] flattenHeaders(Map<String, ? extends List<String>> headers) {
return headers.entrySet().stream()
.flatMap(x -> x.getValue()
.stream()
.flatMap(y -> Stream.of(x.getKey(), y))
)
.toArray(String[]::new);
}
}
}
—
the requestExecutor.exec(String url, Map<String, ? extends List<String>> headers, String body)
method can accept the headers but I am not seeing a graphql client method that can pass or accept httpheader.
What I am currently using is –
var request = new GraphQLQueryRequest(
OurStoreGraphQLQuery.newRequest().oneStoreId(oneStoreId).build(),
RESPONSE_PROJECTION;
GraphQLResponse response = graphQLClient.executeQuery(request.serialize());
Neither of the above i.e. GraphQLQueryRequest
constructor or executeQuery
method has a overloaded equivalent that accept HttpHeader and in-turn pass it to requestExecutor::exec
method.
-
What is the point of exec method accepting
headers
if it can not be passed by the user code with out creating a new instance ofRequestExecutor
. -
Now how can i pass header to the graphql request?
Probably I can use the below style as mentioned in java-client/#plug-in-your-own-http-client docs –
CustomGraphQLClient client = GraphQLClient.createCustom(url, (url, headers, body) -> {
HttpHeaders httpHeaders = new HttpHeaders();
headers.forEach(httpHeaders::addAll);
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, httpHeaders),String.class);
return new HttpResponse(exchange.getStatusCodeValue(), exchange.getBody());
});
GraphQLResponse graphQLResponse = client.executeQuery(query, emptyMap(), "SubmitReview");
String submittedBy = graphQLResponse.extractValueAsObject("submitReview.submittedBy", String.class);
— but looks like i will have to create a custom client each time my header changes. Is that right??