1709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardpackage fi.iki.elonen;
2709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
3709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard/*
4709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * #%L
5709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * NanoHttpd-Webserver
6709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * %%
7709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * Copyright (C) 2012 - 2015 nanohttpd
8709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * %%
9709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * Redistribution and use in source and binary forms, with or without modification,
10709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * are permitted provided that the following conditions are met:
11709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *
12709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * 1. Redistributions of source code must retain the above copyright notice, this
13709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *    list of conditions and the following disclaimer.
14709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *
15709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * 2. Redistributions in binary form must reproduce the above copyright notice,
16709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *    this list of conditions and the following disclaimer in the documentation
17709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *    and/or other materials provided with the distribution.
18709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *
19709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * 3. Neither the name of the nanohttpd nor the names of its contributors
20709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *    may be used to endorse or promote products derived from this software without
21709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *    specific prior written permission.
22709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard *
23709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * OF THE POSSIBILITY OF SUCH DAMAGE.
33709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * #L%
34709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard */
35709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
36709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport java.io.ByteArrayOutputStream;
37709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport java.io.FileInputStream;
38709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport java.io.IOException;
39709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport java.io.InputStream;
40709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport java.io.PipedInputStream;
41709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport java.io.PipedOutputStream;
42709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
43709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.apache.http.HttpEntity;
44709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.apache.http.client.methods.CloseableHttpResponse;
45709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.apache.http.client.methods.HttpGet;
46709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.apache.http.client.methods.HttpOptions;
47709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.apache.http.impl.client.CloseableHttpClient;
48709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.apache.http.impl.client.HttpClients;
49709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.junit.AfterClass;
50709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.junit.Assert;
51709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.junit.BeforeClass;
52709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardimport org.junit.Test;
53709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
54709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard/**
55709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard * @author Matthieu Brouillard [matthieu@brouillard.fr]
56709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard */
57709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillardpublic class TestCorsHttpServer extends AbstractTestHttpServer {
58709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
59709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    private static PipedOutputStream stdIn;
60709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
61709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    private static Thread serverStartThread;
62709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
63709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    @BeforeClass
64709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    public static void setUp() throws Exception {
65709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        stdIn = new PipedOutputStream();
66709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        System.setIn(new PipedInputStream(stdIn));
67709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        serverStartThread = new Thread(new Runnable() {
68709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
69709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            @Override
70709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            public void run() {
71709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                String[] args = {
72709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "--host",
73709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "localhost",
74709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "--port",
75709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "9090",
76709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "--dir",
77709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "src/test/resources",
78709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    "--cors"
79709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                };
80709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                SimpleWebServer.main(args);
81709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            }
82709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        });
83709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        serverStartThread.start();
84709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        // give the server some tine to start.
85709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Thread.sleep(100);
86709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    }
87709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
88709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    @AfterClass
89709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    public static void tearDown() throws Exception {
90709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        stdIn.write("\n\n".getBytes());
91709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        serverStartThread.join(2000);
92709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertFalse(serverStartThread.isAlive());
93709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    }
94709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
95709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    @Test
96709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    public void doTestOption() throws Exception {
97709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        CloseableHttpClient httpclient = HttpClients.createDefault();
98709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        HttpOptions httpOption = new HttpOptions("http://localhost:9090/xxx/yyy.html");
99709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        CloseableHttpResponse response = httpclient.execute(httpOption);
100709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
101709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertNotNull("Cors should have added a header: Access-Control-Allow-Origin", response.getLastHeader("Access-Control-Allow-Origin"));
102709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertEquals("Cors should have added a header: Access-Control-Allow-Origin: *", "*", response.getLastHeader("Access-Control-Allow-Origin").getValue());
103709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        response.close();
104709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    }
105709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
106709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    @Test
107709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    public void doSomeBasicTest() throws Exception {
108709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        CloseableHttpClient httpclient = HttpClients.createDefault();
109709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        HttpGet httpget = new HttpGet("http://localhost:9090/testdir/test.html");
110709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        CloseableHttpResponse response = httpclient.execute(httpget);
111709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        HttpEntity entity = response.getEntity();
112709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        String string = new String(readContents(entity), "UTF-8");
113709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
114709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertNotNull("Cors should have added a header: Access-Control-Allow-Origin", response.getLastHeader("Access-Control-Allow-Origin"));
115709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertEquals("Cors should have added a header: Access-Control-Allow-Origin: *", "*", response.getLastHeader("Access-Control-Allow-Origin").getValue());
116709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertEquals("<html>\n<head>\n<title>dummy</title>\n</head>\n<body>\n\t<h1>it works</h1>\n</body>\n</html>", string);
117709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        response.close();
118709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    }
119709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
120709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    @Test
121709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    public void testAccessControlAllowHeaderUsesDefaultsWithoutSystemProperty() throws Exception {
122709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertNull("no System " + SimpleWebServer.ACCESS_CONTROL_ALLOW_HEADER_PROPERTY_NAME + " shoudl be set",
123709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                System.getProperty(SimpleWebServer.ACCESS_CONTROL_ALLOW_HEADER_PROPERTY_NAME));
124709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
125709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        CloseableHttpClient httpclient = HttpClients.createDefault();
126709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        HttpOptions httpOption = new HttpOptions("http://localhost:9090/xxx/yyy.html");
127709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        CloseableHttpResponse response = httpclient.execute(httpOption);
128709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
129709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertEquals("Cors should have added a header: Access-Control-Allow-Headers: " + SimpleWebServer.DEFAULT_ALLOWED_HEADERS,
130709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                SimpleWebServer.DEFAULT_ALLOWED_HEADERS, response.getLastHeader("Access-Control-Allow-Headers").getValue());
131709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        response.close();
132709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    }
133709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
134709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    @Test
135709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    public void testAccessControlAllowHeaderUsesSystemPropertyWhenSet() throws Exception {
136709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        Assert.assertNull("no System " + SimpleWebServer.ACCESS_CONTROL_ALLOW_HEADER_PROPERTY_NAME + " shoudl be set",
137709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                System.getProperty(SimpleWebServer.ACCESS_CONTROL_ALLOW_HEADER_PROPERTY_NAME));
138709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
139709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        final String expectedValue = "origin";
140709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        System.setProperty(SimpleWebServer.ACCESS_CONTROL_ALLOW_HEADER_PROPERTY_NAME, expectedValue);
141709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard
142709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        try {
143709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            CloseableHttpClient httpclient = HttpClients.createDefault();
144709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            HttpOptions httpOption = new HttpOptions("http://localhost:9090/xxx/yyy.html");
145709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            CloseableHttpResponse response = httpclient.execute(httpOption);
146709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            Assert.assertEquals(200, response.getStatusLine().getStatusCode());
147709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            Assert.assertEquals("Cors should have added a header: Access-Control-Allow-Headers: " + expectedValue, expectedValue,
148709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard                    response.getLastHeader("Access-Control-Allow-Headers").getValue());
149709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            response.close();
150709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        } finally {
151709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard            System.clearProperty(SimpleWebServer.ACCESS_CONTROL_ALLOW_HEADER_PROPERTY_NAME);
152709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard        }
153709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard    }
154709bd63d3d1d89e4bb35a2f721d3b2d07cec892dMatthieu Brouillard}
155