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