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

no.ssb.lds.graphql.GraphqlHttpHandler Maven / Gradle / Ivy

There is a newer version: 0.16
Show newest version
package no.ssb.lds.graphql;

import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
import io.undertow.attribute.ExchangeAttributes;
import io.undertow.predicate.Predicate;
import io.undertow.predicate.Predicates;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import io.undertow.util.StatusCodes;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Deque;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Scanner;

import static io.undertow.util.Headers.ALLOW;
import static io.undertow.util.Methods.GET;
import static io.undertow.util.Methods.GET_STRING;
import static io.undertow.util.Methods.OPTIONS;
import static io.undertow.util.Methods.OPTIONS_STRING;
import static io.undertow.util.Methods.POST;
import static io.undertow.util.Methods.POST_STRING;

/**
 * Handler that executes GraphQL queries.
 * 

* Supports GET and POST requests as described on the * GraphQL website */ public class GraphqlHttpHandler implements HttpHandler { private static final Predicate IS_JSON = Predicates.regex( ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), "application/(.*\\+)?json" ); private static final Predicate IS_GRAPHQL = Predicates.regex( ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), "application/(.*\\+)?graphql" ); private final GraphQL graphQl; /** * Constructs a handler with the specified GraphQL instance. * * @param graphQl the instance that will execute the queries. * @throws NullPointerException if the graphQl was null. */ public GraphqlHttpHandler(GraphQL graphQl) { this.graphQl = Objects.requireNonNull(graphQl); } private static Optional extractParam(Map> parameters, String name) { Deque parameter = parameters.get(name); if (parameter != null && !parameter.isEmpty()) { String first = parameter.removeFirst(); if (!parameter.isEmpty()) { throw new IllegalArgumentException( String.format("more than one \"%s\" parameter", name) ); } return Optional.of(first); } return Optional.empty(); } private static JSONObject toJson(HttpServerExchange exchange) throws IOException { try (InputStream bi = new BufferedInputStream(exchange.getInputStream())) { JSONTokener tokener = new JSONTokener(new InputStreamReader( bi, Charset.forName(exchange.getRequestCharset()) )); return new JSONObject(tokener); } } private static String toString(HttpServerExchange exchange) throws IOException { try (InputStream i = new BufferedInputStream(exchange.getInputStream())) { Scanner scanner = new Scanner(i, Charset.forName(exchange.getRequestCharset())).useDelimiter("\\A"); return scanner.hasNext() ? scanner.next() : ""; } } @Override public void handleRequest(HttpServerExchange exchange) throws Exception { if (exchange.isInIoThread()) { exchange.dispatch(this); return; } HttpString method = exchange.getRequestMethod(); if (method.equals(OPTIONS)) { HeaderMap headers = exchange.getResponseHeaders(); headers.add(ALLOW, GET.toString()); headers.add(ALLOW, POST_STRING); headers.add(ALLOW, GET_STRING); headers.add(ALLOW, OPTIONS_STRING); return; } exchange.startBlocking(); ExecutionInput.Builder executionInput = ExecutionInput.newExecutionInput(); if (method.equals(POST)) { if (IS_GRAPHQL.resolve(exchange)) { executionInput.query(toString(exchange)); } else if (IS_JSON.resolve(exchange)) { JSONObject json = toJson(exchange); executionInput.query(json.getString("query")); if (json.has("variables") && !json.isNull("variables")) { executionInput.variables(json.getJSONObject("variables").toMap()); } if (json.has("operationName")) { executionInput.operationName(json.getString("operationName")); } } else { exchange.setStatusCode(StatusCodes.UNSUPPORTED_MEDIA_TYPE); return; } } else if (method.equals(GET)) { Map> parameters = exchange.getQueryParameters(); Optional query = extractParam(parameters, "query"); query.ifPresent(executionInput::query); Optional operationName = extractParam(parameters, "operationName"); operationName.ifPresent(executionInput::operationName); Optional variables = extractParam(parameters, "variables"); variables.map(JSONObject::new).map(JSONObject::toMap) .ifPresent(executionInput::variables); } else { exchange.setStatusCode(StatusCodes.METHOD_NOT_ALLOWED); return; } // Add context. executionInput.context(new GraphQLUndertowContext(exchange, executionInput.build())); // Execute ExecutionResult result = graphQl.execute(executionInput); // Serialize JSONObject json = new JSONObject(result.toSpecification()); exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json"); exchange.setStatusCode(StatusCodes.OK); exchange.getResponseSender().send(json.toString()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy