/*
 * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import jdk.test.lib.net.SimpleSSLContext;
import javax.net.ssl.SSLContext;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.httpclient.test.lib.common.HttpServerAdapters;
import jdk.httpclient.test.lib.http2.Http2TestServer;
import static java.lang.String.format;
import static java.lang.System.out;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;

/**
 * @test
 * @summary This test verifies that if an h2 connection going through a
 *          proxy P is downgraded to HTTP/1.1, then a new h2 request
 *          going to a different host through the same proxy will not
 *          be preemptively downgraded. That, is the stack should attempt
 *          a new h2 connection to the new host. It also verifies that
 *          the stack sends the appropriate "host" header to the proxy.
 * @bug 8196967 8222527
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 * @build jdk.httpclient.test.lib.common.HttpServerAdapters jdk.test.lib.net.SimpleSSLContext
 *        DigestEchoServer HttpsTunnelTest
 * @run main/othervm -Dtest.requiresHost=true
 *                   -Djdk.httpclient.HttpClient.log=headers
 *                   -Djdk.internal.httpclient.debug=true HttpsTunnelTest
 * @run main/othervm -Dtest.requiresHost=true
 *                   -Djdk.httpclient.allowRestrictedHeaders=host
 *                   -Djdk.httpclient.HttpClient.log=headers
 *                   -Djdk.internal.httpclient.debug=true HttpsTunnelTest
 *
 */

public class HttpsTunnelTest implements HttpServerAdapters {

    static final String data[] = {
        "Lorem ipsum",
        "dolor sit amet",
        "consectetur adipiscing elit, sed do eiusmod tempor",
        "quis nostrud exercitation ullamco",
        "laboris nisi",
        "ut",
        "aliquip ex ea commodo consequat." +
        "Duis aute irure dolor in reprehenderit in voluptate velit esse" +
        "cillum dolore eu fugiat nulla pariatur.",
        "Excepteur sint occaecat cupidatat non proident."
    };

    static final SSLContext context;
    static {
        try {
            context = new SimpleSSLContext().get();
            SSLContext.setDefault(context);
        } catch (Exception x) {
            throw new ExceptionInInitializerError(x);
        }
    }

    HttpsTunnelTest() {
    }

    public HttpClient newHttpClient(ProxySelector ps) {
        HttpClient.Builder builder = HttpClient
                .newBuilder()
                .sslContext(context)
                .proxy(ps);
        return builder.build();
    }

    public static void main(String[] args) throws Exception {
        HttpTestServer http1Server =
                HttpTestServer.create(HTTP_1_1, context);
        http1Server.addHandler(new HttpTestEchoHandler(), "/");
        http1Server.start();
        HttpTestServer http2Server = HttpTestServer.create(HTTP_2, SSLContext.getDefault());
        http2Server.addHandler(new HttpTestEchoHandler(), "/");
        http2Server.start();

        DigestEchoServer.TunnelingProxy proxy = DigestEchoServer.createHttpsProxyTunnel(
                DigestEchoServer.HttpAuthSchemeType.NONE);

        try {
            URI uri1 = new URI("https://" + http1Server.serverAuthority() + "/foo/https1");
            URI uri2 = new URI("https://" + http2Server.serverAuthority() + "/foo/https2");

            boolean provideCustomHost = "host".equalsIgnoreCase(
                    System.getProperty("jdk.httpclient.allowRestrictedHeaders",""));

            String customHttp1Host = null, customHttp2Host = null;
            if (provideCustomHost) {
                customHttp1Host = makeCustomHostString(http1Server, uri1);
                out.println("HTTP/1.1: <" + uri1 + "> [custom host: " + customHttp1Host + "]");
                customHttp2Host = makeCustomHostString(http2Server, uri2);
                out.println("HTTP/2:   <" + uri2 + "> [custom host: " + customHttp2Host + "]");
            }

            ProxySelector ps = ProxySelector.of(proxy.getProxyAddress());
                    //HttpClient.Builder.NO_PROXY;
            HttpsTunnelTest test = new HttpsTunnelTest();
            HttpClient client = test.newHttpClient(ps);
            out.println("Proxy is: " + ps.select(uri2));

            List<String> lines = List.of(Arrays.copyOfRange(data, 0, data.length));
            assert lines.size() == data.length;
            String body = lines.stream().collect(Collectors.joining("\r\n"));
            HttpRequest.BodyPublisher reqBody = HttpRequest.BodyPublishers.ofString(body);
            HttpRequest.Builder req1Builder = HttpRequest
                    .newBuilder(uri1)
                    .version(Version.HTTP_2)
                    .POST(reqBody);
            if (provideCustomHost) req1Builder.header("host", customHttp1Host);
            HttpRequest req1 = req1Builder.build();
            out.println("\nPosting to HTTP/1.1 server at: " + req1);
            HttpResponse<Stream<String>> response = client.send(req1, BodyHandlers.ofLines());
            out.println("Checking response...");
            if (response.statusCode() != 200) {
                throw new RuntimeException("Unexpected status code: " + response);
            }
            if (response.version() != HTTP_1_1) {
                throw new RuntimeException("Unexpected protocol version: "
                        + response.version());
            }
            List<String> respLines = response.body().collect(Collectors.toList());
            if (!lines.equals(respLines)) {
                throw new RuntimeException("Unexpected response 1: " + respLines);
            }

            HttpRequest.BodyPublisher reqBody2 = HttpRequest.BodyPublishers.ofString(body);
            HttpRequest.Builder req2Builder = HttpRequest
                    .newBuilder(uri2)
                    .version(Version.HTTP_2)
                    .POST(reqBody2);
            if (provideCustomHost) req2Builder.header("host", customHttp2Host);
            HttpRequest req2 = req2Builder.build();
            out.println("\nPosting to HTTP/2 server at: " + req2);
            response = client.send(req2, BodyHandlers.ofLines());
            out.println("Checking response...");
            if (response.statusCode() != 200) {
                throw new RuntimeException("Unexpected status code: " + response);
            }
            if (response.version() != Version.HTTP_2) {
                throw new RuntimeException("Unexpected protocol version: "
                        + response.version());
            }
            respLines = response.body().collect(Collectors.toList());
            if (!lines.equals(respLines)) {
                throw new RuntimeException("Unexpected response 2: " + respLines);
            }
        } catch(Throwable t) {
            out.println("Unexpected exception: exiting: " + t);
            t.printStackTrace();
            throw t;
        } finally {
            proxy.stop();
            http1Server.stop();
            http2Server.stop();
        }
    }

    /**
     * Builds a custom host string that is different to what is in the URI
     * authority, that is textually different than what the stack would
     * send. For CONNECT we should ignore any custom host settings.
     * The tunnelling proxy will fail with badRequest 400 if it receives
     * the custom host instead of the expected URI authority string.
     * @param  server The target server.
     * @param  uri    The URI to the target server
     * @return a host value for the custom host header.
     */
    static final String makeCustomHostString(HttpTestServer server, URI uri) {
        String customHttpHost;
        if (server.serverAuthority().contains("localhost")) {
            customHttpHost = InetAddress.getLoopbackAddress().getHostAddress();
        } else {
            customHttpHost = InetAddress.getLoopbackAddress().getHostName();
        }
        if (customHttpHost.contains(":")) customHttpHost = "[" + customHttpHost + "]";
        if (uri.getPort() != -1) customHttpHost = customHttpHost + ":" + uri.getPort();
        return customHttpHost;
    }

}
