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

com.tailoredshapes.valkyrie.adapters.Jetty Maven / Gradle / Ivy

The newest version!
package com.tailoredshapes.valkyrie.adapters;

import com.tailoredshapes.stash.Stash;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.KeyStore;
import java.util.function.Consumer;
import java.util.function.Function;

import static com.tailoredshapes.underbar.Die.die;
import static com.tailoredshapes.underbar.Die.rethrow;
import static com.tailoredshapes.valkyrie.servlet.Servlet.buildRequestMap;
import static com.tailoredshapes.valkyrie.servlet.Servlet.updateServletResponse;


/**
 * Created by tmarsh on 1/19/17.
 */
public class Jetty {
    private static AbstractHandler proxyHandler(Function handler) {
        return new AbstractHandler() {
            @Override
            public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
                Stash requestMap = buildRequestMap(request);
                Stash responseMap = handler.apply(requestMap);
                updateServletResponse(response, responseMap);
                baseRequest.setHandled(true);
            }
        };
    }

    private static HttpConfiguration httpConfig(Stash options) {
        HttpConfiguration conf = new HttpConfiguration();
        conf.setSendDateHeader(options.get("send-date-header?", true));
        conf.setOutputBufferSize(options.get("output-buffer-size", 32768));
        conf.setRequestHeaderSize(options.get("request-header-size", 8192));
        conf.setResponseHeaderSize(options.get("response-header-size", 8192));
        conf.setSendServerVersion(options.get("send-server-version?", true));
        return conf;
    }

    private static ServerConnector httpConnector(Server server, Stash options) {
        HttpConnectionFactory connectionFactory = new HttpConnectionFactory(httpConfig(options));
        ServerConnector serverConnector = new ServerConnector(server, connectionFactory);
        serverConnector.setPort(options.get("port", 80));
        serverConnector.setHost(options.get("host", "localhost"));
        serverConnector.setIdleTimeout(options.get("max-idle-time", 200000));
        return serverConnector;
    }

    private static SslContextFactory sslContextFactory(Stash options) {
        SslContextFactory context = new SslContextFactory();
        Object keystore = options.get("keystore");
        if (keystore instanceof String) {
            context.setKeyStorePath((String) keystore);
        }
        if (keystore instanceof KeyStore) {
            context.setKeyStore((KeyStore) keystore);
        }

        context.setKeyStorePassword(options.get("key-password"));

        if(options.contains("truststore")){
            Object truststore = options.get("truststore");
            if (truststore instanceof String) {
                context.setTrustStorePath((String) truststore);
            }
            if (truststore instanceof KeyStore) {
                context.setTrustStore((KeyStore) truststore);
            }
            if (options.contains("trust-password")) {
                context.setTrustStorePassword(options.get("trust-password"));
            }
        }

        String clientAuth = options.get("client-auth", "none");
        switch (clientAuth) {
            case "need":
                context.setNeedClientAuth(true);
                break;
            case "want":
                context.setWantClientAuth(true);
        }
        if(options.contains("exclude-ciphers")){
            context.addExcludeCipherSuites(options.get("exclude-ciphers"));
        }

        if(options.contains("exclude-protocols")){
            context.addExcludeProtocols(options.get("excludeo-protocols"));
        }

        return context;
    }

    private static ServerConnector sslConnector(Server server, Stash options){
        Integer sslPort = options.get("ssl-port", 443);
        HttpConfiguration config = httpConfig(options);
        config.setSecureScheme("https");
        config.setSecurePort(sslPort);
        config.addCustomizer(new SecureRequestCustomizer());
        HttpConnectionFactory httpFactory = new HttpConnectionFactory(config);
        SslConnectionFactory sslFactory = new SslConnectionFactory(sslContextFactory(options), "http/1.1");

        ServerConnector serverConnector = new ServerConnector(server, sslFactory, httpFactory);
        serverConnector.setPort(sslPort);
        serverConnector.setHost(options.get("host"));
        serverConnector.setIdleTimeout(options.get("max-idle-time", 200000));
        return serverConnector;
    }

    private static ThreadPool createThreadPool(Stash options){
        QueuedThreadPool pool = new QueuedThreadPool(options.get("max-thread", 50));
        pool.setMinThreads(options.get("min-threads", 8));
        pool.setDaemon(options.get("daemon?", false));
        return pool;
    }

    private static Server createServer(Stash options){
        Server server = new Server(createThreadPool(options));
        if(options.get("http?",true)){
            server.addConnector(httpConnector(server, options));
        }
        if(options.get("ssl?", false) || options.contains("ssl-port")){
            server.addConnector(sslConnector(server, options));
        }
        return server;
    }

    /**
     *   "Start a Jetty webserver to serve the given handler according to the
     supplied stash of options:

     "configurator"         - a function called with the Jetty Server instance
     "async?"               - if true, treat the handler as asynchronous
     "port"                 - the port to listen on (defaults to 80)
     "host"                 - the hostname to listen on
     "join?"                - blocks the thread until server ends (defaults to true)
     "daemon?"              - use daemon threads (defaults to false)
     "http?"                - listen on :port for HTTP traffic (defaults to true)
     "ssl?"                 - allow connections over HTTPS
     "ssl-port"             - the SSL port to listen on (defaults to 443, implies ssl? is true)
     "exclude-ciphers"      - When :ssl? is true, exclude these cipher suites
     "exclude-protocols"    - When :ssl? is true, exclude these protocols
     "keystore"             - the keystore to use for SSL connections
     "key-password"         - the password to the keystore
     "truststore"           - a truststore to use for SSL connections
     "trust-password"       - the password to the truststore
     "max-threads"          - the maximum number of threads to use (default 50)
     "min-threads"          - the minimum number of threads to use (default 8)
     "max-idle-time"        - the maximum idle time in milliseconds for a connection(default 200000)
     "client-auth"          - SSL client certificate authenticate, may be set to "need","want" or "none" (defaults to :none)
     "send-date-header?"    - add a date header to the response (default true)
     "output-buffer-size"   - the response body buffer size (default 32768)
     "request-header-size"  - the maximum size of a request header (default 8192)
     "response-header-size" - the maximum size of a response header (default 8192)
     "send-server-version?" - add Server header to HTTP response (default true)"
     * @param handler
     * @param options
     * @return
     */

    public static Server runJetty(Function handler, Stash options){
        Server server = createServer(options.dissoc("configurator"));
        server.setHandler(proxyHandler(handler));
        if(options.contains("configurator")){
            Consumer configurator = options.get("configurator");
            configurator.accept(server);
        }
        try{
            server.start();
            if(options.get("join?", true)){
                server.join();

            }
        } catch (Exception e) {
            rethrow(server::stop);
            die(e, e.getMessage());
        }
        return server;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy