/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.coyote.http11;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Assert;
import org.junit.Test;

import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.SimpleHttpClient;
import org.apache.catalina.startup.TesterServlet;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.B2CConverter;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;

public class TestHttp11Processor extends TomcatBaseTest {

    @Test
    public void testResponseWithErrorChunked() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add protected servlet
        Tomcat.addServlet(ctx, "ChunkedResponseWithErrorServlet",
                new ResponseWithErrorServlet(true));
        ctx.addServletMappingDecoded("/*", "ChunkedResponseWithErrorServlet");

        tomcat.start();

        String request =
                "GET /anything HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: any" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 200 response followed by an incomplete chunked
        // body.
        Assert.assertTrue(client.isResponse200());
        // Should use chunked encoding
        String transferEncoding = null;
        for (String header : client.getResponseHeaders()) {
             if (header.startsWith("Transfer-Encoding:")) {
                transferEncoding = header.substring(18).trim();
            }
        }
        Assert.assertEquals("chunked", transferEncoding);
        // There should not be an end chunk
        Assert.assertFalse(client.getResponseBody().endsWith("0"));
        // The last portion of text should be there
        Assert.assertTrue(client.getResponseBody().endsWith("line03"));
    }

    private static class ResponseWithErrorServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        private final boolean useChunks;

        public ResponseWithErrorServlet(boolean useChunks) {
            this.useChunks = useChunks;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {

            resp.setContentType("text/plain");
            resp.setCharacterEncoding("UTF-8");
            if (!useChunks) {
                // Longer than it needs to be because response will fail before
                // it is complete
                resp.setContentLength(100);
            }
            PrintWriter pw = resp.getWriter();
            pw.print("line01");
            pw.flush();
            resp.flushBuffer();
            pw.print("line02");
            pw.flush();
            resp.flushBuffer();
            pw.print("line03");

            // Now throw a RuntimeException to end this request
            throw new ServletException("Deliberate failure");
        }
    }


    @Test
    public void testWithUnknownExpectation() throws Exception {
        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            "Expect: unknown" + SimpleHttpClient.CRLF +
            SimpleHttpClient.CRLF;

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse417());
    }


    @Test
    public void testWithTEVoid() throws Exception {
        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            "Transfer-encoding: void" + SimpleHttpClient.CRLF +
            "Content-Length: 9" + SimpleHttpClient.CRLF +
            "Content-Type: application/x-www-form-urlencoded" +
                    SimpleHttpClient.CRLF +
                    SimpleHttpClient.CRLF +
            "test=data";

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse501());
    }


    @Test
    public void testWithTEBuffered() throws Exception {
        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            "Transfer-encoding: buffered" + SimpleHttpClient.CRLF +
            "Content-Length: 9" + SimpleHttpClient.CRLF +
            "Content-Type: application/x-www-form-urlencoded" +
                    SimpleHttpClient.CRLF +
                    SimpleHttpClient.CRLF +
            "test=data";

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse501());
    }


    @Test
    public void testWithTEChunked() throws Exception {
        doTestWithTEChunked(false);
    }


    @Test
    public void testWithTEChunkedWithCL() throws Exception {
        // Should be ignored
        doTestWithTEChunked(true);
    }


    private void doTestWithTEChunked(boolean withCL) throws Exception {

        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /test/echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            (withCL ? "Content-length: 1" + SimpleHttpClient.CRLF : "") +
            "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
            "Content-Type: application/x-www-form-urlencoded" +
                    SimpleHttpClient.CRLF +
            "Connection: close" + SimpleHttpClient.CRLF +
            SimpleHttpClient.CRLF +
            "9" + SimpleHttpClient.CRLF +
            "test=data" + SimpleHttpClient.CRLF +
            "0" + SimpleHttpClient.CRLF +
            SimpleHttpClient.CRLF;

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse200());
        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    }


    @Test
    public void testWithTEIdentity() throws Exception {
        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /test/echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            "Transfer-encoding: identity" + SimpleHttpClient.CRLF +
            "Content-Length: 9" + SimpleHttpClient.CRLF +
            "Content-Type: application/x-www-form-urlencoded" +
                    SimpleHttpClient.CRLF +
            "Connection: close" + SimpleHttpClient.CRLF +
                SimpleHttpClient.CRLF +
            "test=data";

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse200());
        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    }


    @Test
    public void testWithTESavedRequest() throws Exception {
        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            "Transfer-encoding: savedrequest" + SimpleHttpClient.CRLF +
            "Content-Length: 9" + SimpleHttpClient.CRLF +
            "Content-Type: application/x-www-form-urlencoded" +
                    SimpleHttpClient.CRLF +
                    SimpleHttpClient.CRLF +
            "test=data";

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse501());
    }


    @Test
    public void testWithTEUnsupported() throws Exception {
        getTomcatInstanceTestWebapp(false, true);

        String request =
            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
            "Host: any" + SimpleHttpClient.CRLF +
            "Transfer-encoding: unsupported" + SimpleHttpClient.CRLF +
            "Content-Length: 9" + SimpleHttpClient.CRLF +
            "Content-Type: application/x-www-form-urlencoded" +
                    SimpleHttpClient.CRLF +
                    SimpleHttpClient.CRLF +
            "test=data";

        Client client = new Client(getPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();
        Assert.assertTrue(client.isResponse501());
    }


    @Test
    public void testPipelining() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add protected servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String requestPart1 =
            "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF;
        String requestPart2 =
            "Host: any" + SimpleHttpClient.CRLF +
            SimpleHttpClient.CRLF;

        final Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {requestPart1, requestPart2});
        client.setRequestPause(1000);
        client.setUseContentLength(true);
        client.connect();

        Runnable send = new Runnable() {
            @Override
            public void run() {
                try {
                    client.sendRequest();
                    client.sendRequest();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        Thread t = new Thread(send);
        t.start();

        // Sleep for 1500 ms which should mean the all of request 1 has been
        // sent and half of request 2
        Thread.sleep(1500);

        // Now read the first response
        client.readResponse(true);
        Assert.assertFalse(client.isResponse50x());
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("OK", client.getResponseBody());

        // Read the second response. No need to sleep, read will block until
        // there is data to process
        client.readResponse(true);
        Assert.assertFalse(client.isResponse50x());
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("OK", client.getResponseBody());
    }


    @Test
    public void testChunking11NoContentLength() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "NoContentLengthFlushingServlet",
                new NoContentLengthFlushingServlet());
        ctx.addServletMappingDecoded("/test", "NoContentLengthFlushingServlet");

        tomcat.start();

        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();
        int rc = getUrl("http://localhost:" + getPort() + "/test", responseBody,
                responseHeaders);

        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
        Assert.assertTrue(responseHeaders.containsKey("Transfer-Encoding"));
        List<String> encodings = responseHeaders.get("Transfer-Encoding");
        Assert.assertEquals(1, encodings.size());
        Assert.assertEquals("chunked", encodings.get(0));
    }

    @Test
    public void testNoChunking11NoContentLengthConnectionClose()
            throws Exception {

        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "NoContentLengthConnectionCloseFlushingServlet",
                new NoContentLengthConnectionCloseFlushingServlet());
        ctx.addServletMappingDecoded("/test",
                "NoContentLengthConnectionCloseFlushingServlet");

        tomcat.start();

        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();
        int rc = getUrl("http://localhost:" + getPort() + "/test", responseBody,
                responseHeaders);

        Assert.assertEquals(HttpServletResponse.SC_OK, rc);

        Assert.assertTrue(responseHeaders.containsKey("Connection"));
        List<String> connections = responseHeaders.get("Connection");
        Assert.assertEquals(1, connections.size());
        Assert.assertEquals("close", connections.get(0));

        Assert.assertFalse(responseHeaders.containsKey("Transfer-Encoding"));

        Assert.assertEquals("OK", responseBody.toString());
    }

    @Test
    public void testBug53677a() throws Exception {
        doTestBug53677(false);
    }

    @Test
    public void testBug53677b() throws Exception {
        doTestBug53677(true);
    }

    private void doTestBug53677(boolean flush) throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "LargeHeaderServlet",
                new LargeHeaderServlet(flush));
        ctx.addServletMappingDecoded("/test", "LargeHeaderServlet");

        tomcat.start();

        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();
        int rc = getUrl("http://localhost:" + getPort() + "/test", responseBody,
                responseHeaders);

        Assert.assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, rc);
        if (responseBody.getLength() > 0) {
            // It will be >0 if the standard error page handling has been
            // triggered
            Assert.assertFalse(responseBody.toString().contains("FAIL"));
        }
    }


    private static CountDownLatch bug55772Latch1 = new CountDownLatch(1);
    private static CountDownLatch bug55772Latch2 = new CountDownLatch(1);
    private static CountDownLatch bug55772Latch3 = new CountDownLatch(1);
    private static boolean bug55772IsSecondRequest = false;
    private static boolean bug55772RequestStateLeaked = false;


    @Test
    public void testBug55772() throws Exception {
        Tomcat tomcat = getTomcatInstance();
        tomcat.getConnector().setProperty("processorCache", "1");
        tomcat.getConnector().setProperty("maxThreads", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "async", new Bug55772Servlet());
        ctx.addServletMappingDecoded("/*", "async");

        tomcat.start();

        String request1 = "GET /async?1 HTTP/1.1\r\n" +
                "Host: localhost:" + getPort() + "\r\n" +
                "Connection: keep-alive\r\n" +
                "Cache-Control: max-age=0\r\n" +
                "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n" +
                "User-Agent: Request1\r\n" +
                "Accept-Encoding: gzip,deflate,sdch\r\n" +
                "Accept-Language: en-US,en;q=0.8,fr;q=0.6,es;q=0.4\r\n" +
                "Cookie: something.that.should.not.leak=true\r\n" +
                "\r\n";

        String request2 = "GET /async?2 HTTP/1.1\r\n" +
                "Host: localhost:" + getPort() + "\r\n" +
                "Connection: keep-alive\r\n" +
                "Cache-Control: max-age=0\r\n" +
                "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n" +
                "User-Agent: Request2\r\n" +
                "Accept-Encoding: gzip,deflate,sdch\r\n" +
                "Accept-Language: en-US,en;q=0.8,fr;q=0.6,es;q=0.4\r\n" +
                "\r\n";

        try (final Socket connection = new Socket("localhost", getPort())) {
            connection.setSoLinger(true, 0);
            Writer writer = new OutputStreamWriter(connection.getOutputStream(),
                    StandardCharsets.US_ASCII);
            writer.write(request1);
            writer.flush();

            bug55772Latch1.await();
            connection.close();
        }

        bug55772Latch2.await();
        bug55772IsSecondRequest = true;

        try (final Socket connection = new Socket("localhost", getPort())) {
            connection.setSoLinger(true, 0);
            Writer writer = new OutputStreamWriter(connection.getOutputStream(),
                    B2CConverter.getCharset("US-ASCII"));
            writer.write(request2);
            writer.flush();
            connection.getInputStream().read();
        }

        bug55772Latch3.await();
        if (bug55772RequestStateLeaked) {
            Assert.fail("State leaked between requests!");
        }
    }


    // https://bz.apache.org/bugzilla/show_bug.cgi?id=57324
    @Test
    public void testNon2xxResponseWithExpectation() throws Exception {
        doTestNon2xxResponseAndExpectation(true);
    }

    @Test
    public void testNon2xxResponseWithoutExpectation() throws Exception {
        doTestNon2xxResponseAndExpectation(false);
    }

    private void doTestNon2xxResponseAndExpectation(boolean useExpectation) throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "echo", new EchoBodyServlet());
        ctx.addServletMappingDecoded("/echo", "echo");

        SecurityCollection collection = new SecurityCollection("All", "");
        collection.addPatternDecoded("/*");
        SecurityConstraint constraint = new SecurityConstraint();
        constraint.addAuthRole("Any");
        constraint.addCollection(collection);
        ctx.addConstraint(constraint);

        tomcat.start();

        byte[] requestBody = "HelloWorld".getBytes(StandardCharsets.UTF_8);
        Map<String,List<String>> reqHeaders = null;
        if (useExpectation) {
            reqHeaders = new HashMap<>();
            List<String> expectation = new ArrayList<>();
            expectation.add("100-continue");
            reqHeaders.put("Expect", expectation);
        }
        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();
        int rc = postUrl(requestBody, "http://localhost:" + getPort() + "/echo",
                responseBody, reqHeaders, responseHeaders);

        Assert.assertEquals(HttpServletResponse.SC_FORBIDDEN, rc);
        List<String> connectionHeaders = responseHeaders.get("Connection");
        if (useExpectation) {
            Assert.assertEquals(1, connectionHeaders.size());
            Assert.assertEquals("close", connectionHeaders.get(0).toLowerCase(Locale.ENGLISH));
        } else {
            Assert.assertNull(connectionHeaders);
        }
    }


    private static class Bug55772Servlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            if (bug55772IsSecondRequest) {
                Cookie[] cookies = req.getCookies();
                if (cookies != null && cookies.length > 0) {
                    for (Cookie cookie : req.getCookies()) {
                        if (cookie.getName().equalsIgnoreCase("something.that.should.not.leak")) {
                            bug55772RequestStateLeaked = true;
                        }
                    }
                }
                bug55772Latch3.countDown();
            } else {
                req.getCookies(); // We have to do this so Tomcat will actually parse the cookies from the request
            }

            req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", Boolean.TRUE);
            AsyncContext asyncContext = req.startAsync();
            asyncContext.setTimeout(5000);

            bug55772Latch1.countDown();

            PrintWriter writer = asyncContext.getResponse().getWriter();
            writer.print('\n');
            writer.flush();

            bug55772Latch2.countDown();
        }
    }


    private static final class LargeHeaderServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        boolean flush = false;

        public LargeHeaderServlet(boolean flush) {
            this.flush = flush;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String largeValue =
                    CharBuffer.allocate(10000).toString().replace('\0', 'x');
            resp.setHeader("x-Test", largeValue);
            if (flush) {
                resp.flushBuffer();
            }
            resp.setContentType("text/plain");
            resp.getWriter().print("FAIL");
        }

    }

    // flushes with no content-length set
    // should result in chunking on HTTP 1.1
    private static final class NoContentLengthFlushingServlet
            extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.setContentType("text/plain");
            resp.getWriter().write("OK");
            resp.flushBuffer();
        }
    }

    // flushes with no content-length set but sets Connection: close header
    // should no result in chunking on HTTP 1.1
    private static final class NoContentLengthConnectionCloseFlushingServlet
            extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.setContentType("text/event-stream");
            resp.addHeader("Connection", "close");
            resp.flushBuffer();
            resp.getWriter().write("OK");
            resp.flushBuffer();
        }
    }

    private static final class Client extends SimpleHttpClient {

        public Client(int port) {
            setPort(port);
        }

        @Override
        public boolean isResponseBodyOK() {
            return getResponseBody().contains("test - data");
        }
    }


    /*
     * Partially read chunked input is not swallowed when it is read during
     * async processing.
     */
    @Test
    public void testBug57621a() throws Exception {
        doTestBug57621(true);
    }


    @Test
    public void testBug57621b() throws Exception {
        doTestBug57621(false);
    }


    private void doTestBug57621(boolean delayAsyncThread) throws Exception {
        Tomcat tomcat = getTomcatInstance();
        Context root = tomcat.addContext("", null);
        Wrapper w = Tomcat.addServlet(root, "Bug57621", new Bug57621Servlet(delayAsyncThread));
        w.setAsyncSupported(true);
        root.addServletMappingDecoded("/test", "Bug57621");

        tomcat.start();

        Bug57621Client client = new Bug57621Client();
        client.setPort(tomcat.getConnector().getLocalPort());

        client.setUseContentLength(true);

        client.connect();

        client.doRequest();
        Assert.assertTrue(client.getResponseLine(), client.isResponse200());
        Assert.assertTrue(client.isResponseBodyOK());

        // Do the request again to ensure that the remaining body was swallowed
        client.resetResponse();
        client.processRequest();
        Assert.assertTrue(client.isResponse200());
        Assert.assertTrue(client.isResponseBodyOK());

        client.disconnect();
    }


    private static class Bug57621Servlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        private final boolean delayAsyncThread;


        public Bug57621Servlet(boolean delayAsyncThread) {
            this.delayAsyncThread = delayAsyncThread;
        }


        @Override
        protected void doPut(HttpServletRequest req, final HttpServletResponse resp)
                throws ServletException, IOException {
            final AsyncContext ac = req.startAsync();
            ac.start(new Runnable() {
                @Override
                public void run() {
                    if (delayAsyncThread) {
                        // Makes the difference between calling complete before
                        // the request body is received of after.
                        try {
                            Thread.sleep(1500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    resp.setContentType("text/plain");
                    resp.setCharacterEncoding("UTF-8");
                    try {
                        resp.getWriter().print("OK");
                    } catch (IOException e) {
                        // Should never happen. Test will fail if it does.
                    }
                    ac.complete();
                }
            });
        }
    }


    private static class Bug57621Client extends SimpleHttpClient {

        private Exception doRequest() {
            try {
                String[] request = new String[2];
                request[0] =
                    "PUT http://localhost:8080/test HTTP/1.1" + CRLF +
                    "Host: localhost:8080" + CRLF +
                    "Transfer-encoding: chunked" + CRLF +
                    CRLF +
                    "2" + CRLF +
                    "OK";

                request[1] =
                    CRLF +
                    "0" + CRLF +
                    CRLF;

                setRequest(request);
                processRequest(); // blocks until response has been read
            } catch (Exception e) {
                return e;
            }
            return null;
        }

        @Override
        public boolean isResponseBodyOK() {
            if (getResponseBody() == null) {
                return false;
            }
            if (!getResponseBody().contains("OK")) {
                return false;
            }
            return true;
        }
    }


    @Test
    public void testBug59310() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Tomcat.addServlet(ctx, "Bug59310", new Bug59310Servlet());
        ctx.addServletMappingDecoded("/test", "Bug59310");

        tomcat.start();

        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();

        int rc = headUrl("http://localhost:" + getPort() + "/test", responseBody,
                responseHeaders);

        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
        Assert.assertEquals(0, responseBody.getLength());
        Assert.assertFalse(responseHeaders.containsKey("Content-Length"));
    }


    private static class Bug59310Servlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            super.doGet(req, resp);
        }

        @Override
        protected void doHead(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
        }
    }


    /*
     * Tests what happens if a request is completed during a dispatch but the
     * request body has not been fully read.
     */
    @Test
    public void testRequestBodySwallowing() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        DispatchingServlet servlet = new DispatchingServlet();
        Wrapper w = Tomcat.addServlet(ctx, "Test", servlet);
        w.setAsyncSupported(true);
        ctx.addServletMappingDecoded("/test", "Test");

        tomcat.start();

        // Hand-craft the client so we have complete control over the timing
        SocketAddress addr = new InetSocketAddress("localhost", getPort());
        Socket socket = new Socket();
        socket.setSoTimeout(300000);
        socket.connect(addr,300000);
        OutputStream os = socket.getOutputStream();
        Writer writer = new OutputStreamWriter(os, "ISO-8859-1");
        InputStream is = socket.getInputStream();
        Reader r = new InputStreamReader(is, "ISO-8859-1");
        BufferedReader reader = new BufferedReader(r);

        // Write the headers
        writer.write("POST /test HTTP/1.1\r\n");
        writer.write("Host: localhost:8080\r\n");
        writer.write("Transfer-Encoding: chunked\r\n");
        writer.write("\r\n");
        writer.flush();

        validateResponse(reader);

        // Write the request body
        writer.write("2\r\n");
        writer.write("AB\r\n");
        writer.write("0\r\n");
        writer.write("\r\n");
        writer.flush();

        // Write the 2nd request
        writer.write("POST /test HTTP/1.1\r\n");
        writer.write("Host: localhost:8080\r\n");
        writer.write("Transfer-Encoding: chunked\r\n");
        writer.write("\r\n");
        writer.flush();

        // Read the 2nd response
        validateResponse(reader);

        // Write the 2nd request body
        writer.write("2\r\n");
        writer.write("AB\r\n");
        writer.write("0\r\n");
        writer.write("\r\n");
        writer.flush();

        // Done
        socket.close();
    }


    private void validateResponse(BufferedReader reader) throws IOException {
        // First line has the response code and should always be 200
        String line = reader.readLine();
        Assert.assertEquals("HTTP/1.1 200 ", line);
        while (!"OK".equals(line)) {
            line = reader.readLine();
        }
    }


    private static class DispatchingServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            if (DispatcherType.ASYNC.equals(req.getDispatcherType())) {
                resp.setContentType("text/plain");
                resp.setCharacterEncoding("UTF-8");
                resp.getWriter().write("OK\n");
            } else {
                req.startAsync().dispatch();
            }
        }
    }

    @Test
    public void testBug61086() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        Bug61086Servlet servlet = new Bug61086Servlet();
        Tomcat.addServlet(ctx, "Test", servlet);
        ctx.addServletMappingDecoded("/test", "Test");

        tomcat.start();

        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();
        int rc = getUrl("http://localhost:" + getPort() + "/test", responseBody, responseHeaders);

        Assert.assertEquals(HttpServletResponse.SC_RESET_CONTENT, rc);
        Assert.assertNotNull(responseHeaders.get("Content-Length"));
        Assert.assertTrue("0".equals(responseHeaders.get("Content-Length").get(0)));
        Assert.assertTrue(responseBody.getLength() == 0);
    }

    private static final class Bug61086Servlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setStatus(205);
        }
    }

    /*
     * Multiple, different Host headers
     */
    @Test
    public void testMultipleHostHeader01() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: a" + SimpleHttpClient.CRLF +
                "Host: b" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    /*
     * Multiple instances of the same Host header
     */
    @Test
    public void testMultipleHostHeader02() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: a" + SimpleHttpClient.CRLF +
                "Host: a" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    @Test
    public void testMissingHostHeader() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    @Test
    public void testInconsistentHostHeader01() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://a/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: b" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    @Test
    public void testInconsistentHostHeader02() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://a:8080/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: b:8080" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    @Test
    public void testInconsistentHostHeader03() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://user:pwd@a/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: b" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    /*
     * Hostname (no port) is included in the request line, but Host header
     * is empty.
     * Added for bug 62739.
     */
    @Test
    public void testInconsistentHostHeader04() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://a/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: " + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    /*
     * Hostname (with port) is included in the request line, but Host header
     * is empty.
     * Added for bug 62739.
     */
    @Test
    public void testInconsistentHostHeader05() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://a:8080/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: " + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }

    /*
     * Hostname (with port and user) is included in the request line, but Host
     * header is empty.
     * Added for bug 62739.
     */
    @Test
    public void testInconsistentHostHeader06() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://user:pwd@a/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: " + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 400 response.
        Assert.assertTrue(client.isResponse400());
    }


    /*
     * Request line host is an exact match for Host header (no port)
     */
    @Test
    public void testConsistentHostHeader01() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new ServerNameTesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://a/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: a" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 200 response.
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("request.getServerName() is [a] and request.getServerPort() is 80", client.getResponseBody());
    }

    /*
     * Request line host is an exact match for Host header (with port)
     */
    @Test
    public void testConsistentHostHeader02() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new ServerNameTesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://a:8080/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: a:8080" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 200 response.
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("request.getServerName() is [a] and request.getServerPort() is 8080", client.getResponseBody());

    }

    /*
     * Request line host is an exact match for Host header
     * (no port, with user info)
     */
    @Test
    public void testConsistentHostHeader03() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new ServerNameTesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET http://user:pwd@a/foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: a" + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 200 response.
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("request.getServerName() is [a] and request.getServerPort() is 80", client.getResponseBody());
    }

    /*
     * Host header exists but its value is an empty string.  This is valid if
     * the request line does not include a hostname/port.
     * Added for bug 62739.
     */
    @Test
    public void testBlankHostHeader01() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new ServerNameTesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host: " + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 200 response.
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("request.getServerName() is [] and request.getServerPort() is " + getPort(), client.getResponseBody());
    }

    /*
     * Host header exists but has its value is empty (and there are multiple
     * spaces after the ':'.  This is valid if the request line does not
     * include a hostname/port.
     * Added for bug 62739.
     */
    @Test
    public void testBlankHostHeader02() throws Exception {
        Tomcat tomcat = getTomcatInstance();

        // This setting means the connection will be closed at the end of the
        // request
        tomcat.getConnector().setAttribute("maxKeepAliveRequests", "1");

        // No file system docBase required
        Context ctx = tomcat.addContext("", null);

        // Add servlet
        Tomcat.addServlet(ctx, "TesterServlet", new ServerNameTesterServlet());
        ctx.addServletMappingDecoded("/foo", "TesterServlet");

        tomcat.start();

        String request =
                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
                "Host:      " + SimpleHttpClient.CRLF +
                 SimpleHttpClient.CRLF;

        Client client = new Client(tomcat.getConnector().getLocalPort());
        client.setRequest(new String[] {request});

        client.connect();
        client.processRequest();

        // Expected response is a 200 response.
        Assert.assertTrue(client.isResponse200());
        Assert.assertEquals("request.getServerName() is [] and request.getServerPort() is " + getPort(), client.getResponseBody());
    }


    /**
     * Test servlet that prints out the values of
     * HttpServletRequest.getServerName() and
     * HttpServletRequest.getServerPort() in the response body, e.g.:
     *
     * "request.getServerName() is [foo] and request.getServerPort() is 8080"
     *
     * or:
     *
     * "request.getServerName() is null and request.getServerPort() is 8080"
     */
    private static class ServerNameTesterServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {

            resp.setContentType("text/plain");
            PrintWriter out = resp.getWriter();

            if (null == req.getServerName())
            {
                out.print("request.getServerName() is null");
            }
            else
            {
                out.print("request.getServerName() is [" + req.getServerName() + "]");
            }

            out.print(" and request.getServerPort() is " + req.getServerPort());
        }
    }
}
