All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xlrit.gears.runner.graphql.GraphQLClient Maven / Gradle / Ivy

There is a newer version: 1.17.1
Show newest version
package com.xlrit.gears.runner.graphql;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.xlrit.gears.runner.runnertarget.InterpreterException;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;

public class GraphQLClient {
	private String token = null;
	public void setToken(String token) { this.token = token; }
	public void clearToken() { this.token = null; }

	private final String url;
	private final ObjectMapper objectMapper;
	private final HttpClient client = HttpClient.newHttpClient();

	private static final ContentType JSON_GRAPHQL = ContentType.create("application/json+graphql");

	public GraphQLClient(String url, ObjectMapper objectMapper) {
		this.url = url;
		this.objectMapper = objectMapper;
	}

	public JsonNode invoke(Operation operation) {
		try {
			HttpRequest request = makeRequest(operation);

			HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());

			JsonNode rootNode = objectMapper.readTree(response.body());
			JsonNode errorsNode = rootNode.at("/errors");
			if (errorsNode.size() > 0) {
				for (JsonNode error : errorsNode) {
					System.out.println(error);
				}
				throw new GraphQLErrorsException(operation, errorsNode);
			}
			return rootNode.get("data");
		} catch (URISyntaxException | GraphQLErrorsException | IOException | InterruptedException e) {
			throw new InterpreterException(e.getMessage(), e);
		}
	}

	private HttpRequest makeRequest(Operation operation) throws URISyntaxException, IOException {
		String query = operation.query.replace('\'', '"');
		ObjectNode payload = objectMapper.createObjectNode();
		payload.put("query", query);
		payload.set("variables", objectMapper.valueToTree(operation.variables));

		HttpRequest.Builder requestBuild = HttpRequest
				.newBuilder()
				.uri(new URI(url));
		if (token != null) requestBuild.header("Authorization", "BEARER " + token);

		if (operation.files == null) {
			return requestBuild
					.header("Content-Type", "application/json")
					.header("Accept", "application/json")
					.POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(payload)))
					.build();
		}

		ObjectNode map = objectMapper.createObjectNode();
		for (int i = 0; i < operation.files.size(); i++) {
			map.set(String.format("file%d", i),
					objectMapper.createArrayNode().add(objectMapper.readTree(String.format("\"variables.files.%d\"", i))));
		}

		MultipartEntityBuilder meb = MultipartEntityBuilder.create()
				.addPart("operations", new StringBody(objectMapper.writeValueAsString(payload), JSON_GRAPHQL))
				.addPart("map", new StringBody(objectMapper.writeValueAsString(map), ContentType.TEXT_PLAIN));
		int i = 0;
		for (File file : operation.files) {
			meb.addBinaryBody(String.format("file%d", i++), file, ContentType.TEXT_PLAIN, file.getName());
		}

		HttpEntity httpEntity = meb.build();
		Pipe pipe = Pipe.open();
		new Thread(() -> {
			try (OutputStream os = Channels.newOutputStream(pipe.sink())) {
				httpEntity.writeTo(os);
			} catch (IOException e) {
				e.printStackTrace();
				throw new InterpreterException(e.getMessage(), e.getCause());
			}
		}).start();

		return requestBuild
				.header("Content-Type", httpEntity.getContentType().getValue())
				.POST(HttpRequest.BodyPublishers.ofInputStream(() -> Channels.newInputStream(pipe.source())))
				.build();
	}

	private static class GraphQLErrorsException extends Exception {
		private final String message;

		public GraphQLErrorsException(Operation operation, JsonNode errorsNode) {
			message = String.format("Error during operation %s: %s", operation.name, errorsNode);
		}

		@Override
		public String getMessage() {
			return message;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy