GQLPlaygroundServlet.java

package net.morimekta.providence.graphql;

import net.morimekta.util.io.IOUtils;
import net.morimekta.util.io.IndentedPrintWriter;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import static net.morimekta.util.collect.UnmodifiableMap.mapOf;

public class GQLPlaygroundServlet extends HttpServlet {
    private final String html;

    public GQLPlaygroundServlet(String title,
                                String queryPath) {
        this(title, queryPath, mapOf());
    }

    public GQLPlaygroundServlet(String title,
                                String queryPath,
                                Map<String, String> headers) {
        this(title, queryPath,
             headers,
             "1.7.20",
             "sha256-cS9Vc2OBt9eUf4sykRWukeFYaInL29+myBmFDSa7F/U=",
             "sha256-GhTyE+McTU79R4+pRO6ih+4TfsTOrpPwD8ReKFzb3PM=",
             "sha256-4QG1Uza2GgGdlBL3RCBCGtGeZB6bDbsw8OltCMGeJsA=");
    }

    private GQLPlaygroundServlet(String title,
                                 String queryPath,
                                 Map<String, String> headers,
                                 String graphiqlVersion,
                                 String cssSRI,
                                 String faviconSRI,
                                 String jsSRI) {
        try {
            String template = IOUtils.readString(getClass().getResourceAsStream(
                    "/net/morimekta/providence/graphql/playground.html"));
            String headersJs = "";
            if (headers != null && !headers.isEmpty()) {
                StringWriter writer = new StringWriter();
                IndentedPrintWriter ipw = new IndentedPrintWriter(writer);
                ipw.append("            headers: {")
                   .begin( "                ");

                AtomicBoolean first = new AtomicBoolean(true);
                headers.forEach((key, value) -> {
                    if (!first.getAndSet(false)) {
                        ipw.append(",");
                    }
                    ipw.formatln("\"%s\": \"%s\"", key, value);
                });

                ipw.end()
                   .appendln("            },")
                   .newline()
                   .flush();
                headersJs = writer.toString();
            }

            html = template
                    .replaceAll("\\{\\{ \\.title \\}\\}", title)
                    .replaceAll("\\{\\{ \\.endpoint \\}\\}", queryPath)
                    .replaceAll("\\{\\{ \\.version \\}\\}", graphiqlVersion)
                    .replaceAll("\\{\\{ \\.cssSRI \\}\\}", cssSRI)
                    .replaceAll("\\{\\{ \\.faviconSRI \\}\\}", faviconSRI)
                    .replaceAll("\\{\\{ \\.jsSRI \\}\\}", jsSRI)
                    .replaceAll("\\{\\{ \\.headers \\}\\}", headersJs);
        } catch (IOException e) {
            throw new UncheckedIOException(e.getMessage(), e);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setStatus(HttpServletResponse.SC_OK);
        resp.getWriter().write(html);
        resp.flushBuffer();
    }
}