/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.airlift.http.client;

import com.google.common.net.HostAndPort;
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import javax.servlet.Servlet;

import java.util.Optional;

import static java.util.Objects.requireNonNull;

public class TestingHttpServer
        implements AutoCloseable
{
    private final Server server;
    private final HostAndPort hostAndPort;

    public TestingHttpServer(Optional<String> keystore, Servlet servlet)
            throws Exception
    {
        requireNonNull(keystore, "keyStore is null");
        requireNonNull(servlet, "servlet is null");

        Server server = new Server();

        HttpConfiguration httpConfiguration = new HttpConfiguration();
        httpConfiguration.setSendServerVersion(false);
        httpConfiguration.setSendXPoweredBy(false);

        ServerConnector connector;
        if (keystore.isPresent()) {
            httpConfiguration.addCustomizer(new SecureRequestCustomizer());

            SslContextFactory sslContextFactory = new SslContextFactory.Client();
            sslContextFactory.setKeyStorePath(keystore.get());
            sslContextFactory.setKeyStorePassword("changeit");
            SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, "http/1.1");

            connector = new ServerConnector(server, sslConnectionFactory, new HttpConnectionFactory(httpConfiguration));
        }
        else {
            HttpConnectionFactory http1 = new HttpConnectionFactory(httpConfiguration);
            HTTP2CServerConnectionFactory http2c = new HTTP2CServerConnectionFactory(httpConfiguration);

            connector = new ServerConnector(server, http1, http2c);
        }

        connector.setIdleTimeout(30000);
        connector.setName(keystore.map(path -> "https").orElse("http"));

        server.addConnector(connector);

        ServletHolder servletHolder = new ServletHolder(servlet);
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        context.setGzipHandler(new GzipHandler());
        context.addServlet(servletHolder, "/*");
        HandlerCollection handlers = new HandlerCollection();
        handlers.addHandler(context);

        server.setHandler(handlers);

        this.server = server;
        this.server.start();
        this.hostAndPort = HostAndPort.fromParts("localhost", connector.getLocalPort());
    }

    public HostAndPort getHostAndPort()
    {
        return hostAndPort;
    }

    @Override
    public void close()
            throws Exception
    {
        server.setStopTimeout(3000);
        server.stop();
    }
}

@@ -584,24 +584,72 @@
 tp.client;%0A%0A
+import com.google.common.collect.ImmutableList;%0A
 import com.g
@@ -678,16 +678,16 @@
 ndPort;%0A
-
 import o
@@ -739,32 +739,73 @@
 nectionFactory;%0A
+import org.eclipse.jetty.server.Handler;%0A
 import org.eclip
@@ -1396,24 +1396,47 @@
 t.Servlet;%0A%0A
+import java.util.List;%0A
 import java.
@@ -1449,16 +1449,52 @@
 ptional;
+%0Aimport java.util.function.Consumer;
 %0A%0Aimport
@@ -1779,32 +1779,310 @@
 Exception%0A    %7B%0A
+        this(keystore, servlet, httpConfiguration -%3E %7B%7D, ImmutableList.of());%0A    %7D%0A%0A    public TestingHttpServer(Optional%3CString%3E keystore, Servlet servlet, Consumer%3CHttpConfiguration%3E configurationDecorator, List%3CHandler%3E additionalHandler)%0A            throws Exception%0A    %7B%0A
         requireN
@@ -2388,16 +2388,74 @@
 (false);
+%0A        configurationDecorator.accept(httpConfiguration);
 %0A%0A      
@@ -3815,32 +3815,32 @@
 erCollection();%0A
-
         handlers
@@ -3858,24 +3858,82 @@
 (context);%0A%0A
+        additionalHandler.forEach(handlers::addHandler);%0A%0A
         serv

Allow modifying configuration and adding Handlers for TestingHttpServer