/*
 * Copyright (c) 2022, 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 java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ProtocolException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpTimeoutException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

import javax.net.ssl.SSLContext;
import jdk.httpclient.test.lib.common.HttpServerAdapters;
import jdk.httpclient.test.lib.http2.Http2TestServer;
import jdk.test.lib.net.SimpleSSLContext;
import jdk.test.lib.net.URIBuilder;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static java.net.http.HttpClient.Version.HTTP_2;

/**
 * @test
 * @bug 8292044
 * @summary Tests behaviour of HttpClient when server responds with 102 or 103 status codes
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.HttpServerAdapters
 *        jdk.httpclient.test.lib.http2.Http2TestServer
 * @run testng/othervm -Djdk.internal.httpclient.debug=true
 * *                   -Djdk.httpclient.HttpClient.log=headers,requests,responses,errors Response1xxTest
 */
public class Response1xxTest implements HttpServerAdapters {
    private static final String EXPECTED_RSP_BODY = "Hello World";

    private ServerSocket serverSocket;
    private Http11Server server;
    private String http1RequestURIBase;


    private HttpTestServer http2Server; // h2c
    private String http2RequestURIBase;


    private SSLContext sslContext;
    private HttpTestServer https2Server;  // h2
    private String https2RequestURIBase;

    private final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;

    @BeforeClass
    public void setup() throws Exception {
        serverSocket = new ServerSocket(0, 0, InetAddress.getLoopbackAddress());
        server = new Http11Server(serverSocket);
        new Thread(server).start();
        http1RequestURIBase = URIBuilder.newBuilder().scheme("http").loopback()
                .port(serverSocket.getLocalPort()).build().toString();

        http2Server = HttpTestServer.create(HTTP_2);
        http2Server.addHandler(new Http2Handler(), "/http2/102");
        http2Server.addHandler(new Http2Handler(), "/http2/103");
        http2Server.addHandler(new Http2Handler(), "/http2/100");
        http2Server.addHandler(new Http2Handler(), "/http2/101");
        http2Server.addHandler(new OKHandler(), "/http2/200");
        http2Server.addHandler(new OnlyInformationalHandler(), "/http2/only-informational");
        http2RequestURIBase = URIBuilder.newBuilder().scheme("http").loopback()
                .port(http2Server.getAddress().getPort())
                .path("/http2").build().toString();

        http2Server.start();
        System.out.println("Started HTTP2 server at " + http2Server.getAddress());

        sslContext = new SimpleSSLContext().get();
        if (sslContext == null) {
            throw new AssertionError("Unexpected null sslContext");
        }
        https2Server = HttpTestServer.create(HTTP_2, sslContext);
        https2Server.addHandler(new Http2Handler(), "/http2/101");
        https2RequestURIBase = URIBuilder.newBuilder().scheme("https").loopback()
                .port(https2Server.getAddress().getPort())
                .path("/http2").build().toString();
        https2Server.start();
        System.out.println("Started (https) HTTP2 server at " + https2Server.getAddress());

    }

    @AfterClass
    public void teardown() throws Throwable {
        try {
            assertNoOutstandingClientOps();
        } finally {
            if (server != null) {
                server.stop = true;
                System.out.println("(HTTP 1.1) Server stop requested");
            }
            if (serverSocket != null) {
                serverSocket.close();
                System.out.println("Closed (HTTP 1.1) server socket");
            }
            if (http2Server != null) {
                http2Server.stop();
                System.out.println("Stopped HTTP2 server");
            }
            if (https2Server != null) {
                https2Server.stop();
                System.out.println("Stopped (https) HTTP2 server");
            }
        }
    }

    private static final class Http11Server implements Runnable {
        private static final int CONTENT_LENGTH = EXPECTED_RSP_BODY.getBytes(StandardCharsets.UTF_8).length;

        private static final String HTTP_1_1_RSP_200 = "HTTP/1.1 200 OK\r\n" +
                "Content-Length: " + CONTENT_LENGTH + "\r\n\r\n" +
                EXPECTED_RSP_BODY;

        private static final String REQ_LINE_FOO = "GET /test/foo HTTP/1.1\r\n";
        private static final String REQ_LINE_BAR = "GET /test/bar HTTP/1.1\r\n";
        private static final String REQ_LINE_HELLO = "GET /test/hello HTTP/1.1\r\n";
        private static final String REQ_LINE_BYE = "GET /test/bye HTTP/1.1\r\n";


        private final ServerSocket serverSocket;
        private volatile boolean stop;

        private Http11Server(final ServerSocket serverSocket) {
            this.serverSocket = serverSocket;
        }

        @Override
        public void run() {
            System.out.println("Server running at " + serverSocket);
            while (!stop) {
                Socket socket = null;
                try {
                    // accept a connection
                    socket = serverSocket.accept();
                    System.out.println("Accepted connection from client " + socket);
                    // read request
                    final String requestLine;
                    try {
                        requestLine = readRequestLine(socket);
                    } catch (Throwable t) {
                        // ignore connections from potential rogue client
                        System.err.println("Ignoring connection/request from client " + socket
                                + " due to exception:");
                        t.printStackTrace();
                        // close the socket
                        safeClose(socket);
                        continue;
                    }
                    System.out.println("Received following request line from client " + socket
                            + " :\n" + requestLine);
                    final int informationalResponseCode;
                    if (requestLine.startsWith(REQ_LINE_FOO)) {
                        // we will send intermediate/informational 102 response
                        informationalResponseCode = 102;
                    } else if (requestLine.startsWith(REQ_LINE_BAR)) {
                        // we will send intermediate/informational 103 response
                        informationalResponseCode = 103;
                    } else if (requestLine.startsWith(REQ_LINE_HELLO)) {
                        // we will send intermediate/informational 100 response
                        informationalResponseCode = 100;
                    } else if (requestLine.startsWith(REQ_LINE_BYE)) {
                        // we will send intermediate/informational 101 response
                        informationalResponseCode = 101;
                    } else {
                        // unexpected client. ignore and close the client
                        System.err.println("Ignoring unexpected request from client " + socket);
                        safeClose(socket);
                        continue;
                    }
                    try (final OutputStream os = socket.getOutputStream()) {
                        // send informational response headers a few times (spec allows them to
                        // be sent multiple times)
                        for (int i = 0; i < 3; i++) {
                            // send 1xx response header
                            if (informationalResponseCode == 101) {
                                os.write(("HTTP/1.1 " + informationalResponseCode + "\r\n" +
                                        "Connection: upgrade\r\n" +
                                        "Upgrade: websocket\r\n\r\n")
                                        .getBytes(StandardCharsets.UTF_8));
                            } else {
                                os.write(("HTTP/1.1 " + informationalResponseCode + "\r\n\r\n")
                                        .getBytes(StandardCharsets.UTF_8));
                            }
                            os.flush();
                            System.out.println("Sent response code " + informationalResponseCode
                                    + " to client " + socket);
                        }
                        // now send a final response
                        System.out.println("Now sending 200 response code to client " + socket);
                        os.write(HTTP_1_1_RSP_200.getBytes(StandardCharsets.UTF_8));
                        os.flush();
                        System.out.println("Sent 200 response code to client " + socket);
                    }
                } catch (Throwable t) {
                    // close the client connection
                    safeClose(socket);
                    // continue accepting any other client connections until we are asked to stop
                    System.err.println("Ignoring exception in server:");
                    t.printStackTrace();
                }
            }
        }

        static String readRequestLine(final Socket sock) throws IOException {
            final InputStream is = sock.getInputStream();
            final StringBuilder sb = new StringBuilder("");
            byte[] buf = new byte[1024];
            while (!sb.toString().endsWith("\r\n\r\n")) {
                final int numRead = is.read(buf);
                if (numRead == -1) {
                    return sb.toString();
                }
                final String part = new String(buf, 0, numRead, StandardCharsets.ISO_8859_1);
                sb.append(part);
            }
            return sb.toString();
        }

        private static void safeClose(final Socket socket) {
            try {
                socket.close();
            } catch (Throwable t) {
                // ignore
            }
        }
    }

    private static class Http2Handler implements HttpTestHandler {

        @Override
        public void handle(final HttpTestExchange exchange) throws IOException {
            final URI requestURI = exchange.getRequestURI();
            final int informationResponseCode;
            if (requestURI.getPath().endsWith("/102")) {
                informationResponseCode = 102;
            } else if (requestURI.getPath().endsWith("/103")) {
                informationResponseCode = 103;
            } else if (requestURI.getPath().endsWith("/100")) {
                informationResponseCode = 100;
            } else if (requestURI.getPath().endsWith("/101")) {
                informationResponseCode = 101;
            } else {
                // unexpected request
                System.err.println("Unexpected request " + requestURI + " from client "
                        + exchange.getRemoteAddress());
                exchange.sendResponseHeaders(400, -1);
                return;
            }
            // send informational response headers a few times (spec allows them to
            // be sent multiple times)
            for (int i = 0; i < 3; i++) {
                exchange.sendResponseHeaders(informationResponseCode, -1);
                System.out.println("Sent " + informationResponseCode + " response code from H2 server");
            }
            // now send 200 response
            try {
                final byte[] body = EXPECTED_RSP_BODY.getBytes(StandardCharsets.UTF_8);
                exchange.sendResponseHeaders(200, body.length);
                System.out.println("Sent 200 response from H2 server");
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(body);
                }
                System.out.println("Sent response body from H2 server");
            } catch (Throwable e) {
                System.err.println("Failed to send response from HTTP2 handler:");
                e.printStackTrace();
                throw e;
            }
        }
    }

    private static class OnlyInformationalHandler implements HttpTestHandler {

        @Override
        public void handle(final HttpTestExchange exchange) throws IOException {
            // we only send informational response and then return
            for (int i = 0; i < 5; i++) {
                exchange.sendResponseHeaders(102, -1);
                System.out.println("Sent 102 response code from H2 server");
                // wait for a while before sending again
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // just return
                    System.err.println("Handler thread interrupted");
                }
            }
        }
    }

    private static class OKHandler implements HttpTestHandler {

        @Override
        public void handle(final HttpTestExchange exchange) throws IOException {
            exchange.sendResponseHeaders(200, -1);
        }
    }

    /**
     * Tests that when a HTTP/1.1 server sends intermediate 1xx response codes and then the final
     * response, the client (internally) will ignore those intermediate informational response codes
     * and only return the final response to the application
     */
    @Test
    public void test1xxForHTTP11() throws Exception {
        final HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .proxy(HttpClient.Builder.NO_PROXY).build();
        TRACKER.track(client);
        final URI[] requestURIs = new URI[]{
                new URI(http1RequestURIBase + "/test/foo"),
                new URI(http1RequestURIBase + "/test/bar"),
                new URI(http1RequestURIBase + "/test/hello")};
        for (final URI requestURI : requestURIs) {
            final HttpRequest request = HttpRequest.newBuilder(requestURI).build();
            System.out.println("Issuing request to " + requestURI);
            final HttpResponse<String> response = client.send(request,
                    HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
            Assert.assertEquals(response.version(), HttpClient.Version.HTTP_1_1,
                    "Unexpected HTTP version in response");
            Assert.assertEquals(response.statusCode(), 200, "Unexpected response code");
            Assert.assertEquals(response.body(), EXPECTED_RSP_BODY, "Unexpected response body");
        }
    }

    /**
     * Tests that when a HTTP2 server sends intermediate 1xx response codes and then the final
     * response, the client (internally) will ignore those intermediate informational response codes
     * and only return the final response to the application
     */
    @Test
    public void test1xxForHTTP2() throws Exception {
        final HttpClient client = HttpClient.newBuilder()
                .version(HTTP_2)
                .proxy(HttpClient.Builder.NO_PROXY).build();
        TRACKER.track(client);
        final URI[] requestURIs = new URI[]{
                new URI(http2RequestURIBase + "/102"),
                new URI(http2RequestURIBase + "/103"),
                new URI(http2RequestURIBase + "/100")};
        for (final URI requestURI : requestURIs) {
            final HttpRequest request = HttpRequest.newBuilder(requestURI).build();
            System.out.println("Issuing request to " + requestURI);
            final HttpResponse<String> response = client.send(request,
                    HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
            Assert.assertEquals(response.version(), HTTP_2,
                    "Unexpected HTTP version in response");
            Assert.assertEquals(response.statusCode(), 200, "Unexpected response code");
            Assert.assertEquals(response.body(), EXPECTED_RSP_BODY, "Unexpected response body");
        }
    }


    /**
     * Tests that when a request is issued with a specific request timeout and the server
     * responds with intermediate 1xx response code but doesn't respond with a final response within
     * the timeout duration, then the application fails with a request timeout
     */
    @Test
    public void test1xxRequestTimeout() throws Exception {
        final HttpClient client = HttpClient.newBuilder()
                .version(HTTP_2)
                .proxy(HttpClient.Builder.NO_PROXY).build();
        TRACKER.track(client);
        final URI requestURI = new URI(http2RequestURIBase + "/only-informational");
        final Duration requestTimeout = Duration.ofSeconds(2);
        final HttpRequest request = HttpRequest.newBuilder(requestURI).timeout(requestTimeout)
                .build();
        System.out.println("Issuing request to " + requestURI);
        // we expect the request to timeout
        Assert.assertThrows(HttpTimeoutException.class, () -> {
            client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
        });
    }

    /**
     * Tests that when the HTTP/1.1 server sends a 101 response when the request hasn't asked
     * for an "Upgrade" then the request fails.
     */
    @Test
    public void testHTTP11Unexpected101() throws Exception {
        final HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .proxy(HttpClient.Builder.NO_PROXY).build();
        TRACKER.track(client);
        final URI requestURI = new URI(http1RequestURIBase + "/test/bye");
        final HttpRequest request = HttpRequest.newBuilder(requestURI).build();
        System.out.println("Issuing request to " + requestURI);
        // we expect the request to fail because the server sent an unexpected 101
        Assert.assertThrows(ProtocolException.class,
                () -> client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)));
    }


    /**
     * Tests that when the HTTP2 server (over HTTPS) sends a 101 response when the request
     * hasn't asked for an "Upgrade" then the request fails.
     */
    @Test
    public void testSecureHTTP2Unexpected101() throws Exception {
        final HttpClient client = HttpClient.newBuilder()
                .version(HTTP_2)
                .sslContext(sslContext)
                .proxy(HttpClient.Builder.NO_PROXY).build();
        TRACKER.track(client);
        final URI requestURI = new URI(https2RequestURIBase + "/101");
        final HttpRequest request = HttpRequest.newBuilder(requestURI).build();
        System.out.println("Issuing request to " + requestURI);
        // we expect the request to fail because the server sent an unexpected 101
        Assert.assertThrows(ProtocolException.class,
                () -> client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)));
    }

    /**
     * Tests that when the HTTP2 server (over plain HTTP) sends a 101 response when the request
     * hasn't asked for an "Upgrade" then the request fails.
     */
    @Test
    public void testPlainHTTP2Unexpected101() throws Exception {
        final HttpClient client = HttpClient.newBuilder()
                .version(HTTP_2)
                .proxy(HttpClient.Builder.NO_PROXY).build();
        TRACKER.track(client);
        // when using HTTP2 version against a "http://" (non-secure) URI
        // the HTTP client (implementation) internally initiates a HTTP/1.1 connection
        // and then does an "Upgrade:" to "h2c". This it does when there isn't already a
        // H2 connection against the target/destination server. So here we initiate a dummy request
        // using the client instance against the same target server and just expect it to return
        // back successfully. Once that connection is established (and internally pooled), the client
        // will then reuse that connection and won't issue an "Upgrade:" and thus we can then
        // start our testing
        warmupH2Client(client);
        // start the actual testing
        final URI requestURI = new URI(http2RequestURIBase + "/101");
        final HttpRequest request = HttpRequest.newBuilder(requestURI).build();
        System.out.println("Issuing request to " + requestURI);
        // we expect the request to fail because the server sent an unexpected 101
        Assert.assertThrows(ProtocolException.class,
                () -> client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)));
    }

    // sends a request and expects a 200 response back
    private void warmupH2Client(final HttpClient client) throws Exception {
        final URI requestURI = new URI(http2RequestURIBase + "/200");
        final HttpRequest request = HttpRequest.newBuilder(requestURI).build();
        System.out.println("Issuing (warmup) request to " + requestURI);
        final HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding());
        Assert.assertEquals(response.statusCode(), 200, "Unexpected response code");
    }

    // verifies that the HttpClient being tracked has no outstanding operations
    private void assertNoOutstandingClientOps() throws AssertionError {
        System.gc();
        final AssertionError refCheckFailure = TRACKER.check(1000);
        if (refCheckFailure != null) {
            throw refCheckFailure;
        }
        // successful test completion
    }
}
