Path: blob/master/test/jdk/sun/net/www/B8185898.java
41149 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 818589826* @modules java.base/sun.net.www27* @library /test/lib28* @run main/othervm B818589829* @summary setRequestProperty(key, null) results in HTTP header without colon in request30*/3132import java.io.*;33import java.net.*;34import java.util.Arrays;35import java.util.List;36import java.util.Map;37import java.util.concurrent.ExecutorService;38import java.util.concurrent.Executors;39import java.util.stream.Collectors;4041import jdk.test.lib.net.URIBuilder;42import sun.net.www.MessageHeader;43import com.sun.net.httpserver.HttpContext;44import com.sun.net.httpserver.HttpExchange;45import com.sun.net.httpserver.HttpHandler;46import com.sun.net.httpserver.HttpServer;4748import static java.nio.charset.StandardCharsets.ISO_8859_1;49import static java.nio.charset.StandardCharsets.UTF_8;5051/*52* Test checks that MessageHeader with key != null and value == null is set correctly53* and printed according to HTTP standard in the format <key>: <value>54* */55public class B8185898 {5657static HttpServer server;58static final String RESPONSE_BODY = "Test response body";59static final String H1 = "X-header1";60static final String H2 = "X-header2";61static final String VALUE = "This test value should appear";62static int port;63static URL url;64static volatile Map<String, List<String>> headers;6566static class Handler implements HttpHandler {6768public void handle(HttpExchange t) throws IOException {69InputStream is = t.getRequestBody();70InetSocketAddress rem = t.getRemoteAddress();71headers = t.getRequestHeaders(); // Get request headers on the server side72is.readAllBytes();73is.close();7475OutputStream os = t.getResponseBody();76t.sendResponseHeaders(200, RESPONSE_BODY.length());77os.write(RESPONSE_BODY.getBytes(UTF_8));78t.close();79}80}8182public static void main(String[] args) throws Exception {83ExecutorService exec = Executors.newCachedThreadPool();84InetAddress loopback = InetAddress.getLoopbackAddress();8586try {87InetSocketAddress addr = new InetSocketAddress(loopback, 0);88server = HttpServer.create(addr, 100);89HttpHandler handler = new Handler();90HttpContext context = server.createContext("/", handler);91server.setExecutor(exec);92server.start();9394port = server.getAddress().getPort();95System.out.println("Server on port: " + port);96url = URIBuilder.newBuilder()97.scheme("http")98.loopback()99.port(port)100.path("/foo")101.toURLUnchecked();102System.out.println("URL: " + url);103testMessageHeader();104testMessageHeaderMethods();105testURLConnectionMethods();106} finally {107server.stop(0);108System.out.println("After server shutdown");109exec.shutdown();110}111}112113// Test message header with malformed message header and fake request line114static void testMessageHeader() {115final String badHeader = "This is not a request line for HTTP/1.1";116final String fakeRequestLine = "This /is/a/fake/status/line HTTP/2.0";117final String expectedHeaders = fakeRequestLine + "\r\n"118+ H1 + ": " + VALUE + "\r\n"119+ H2 + ": " + VALUE + "\r\n"120+ badHeader + ":\r\n\r\n";121122MessageHeader header = new MessageHeader();123header.add(H1, VALUE);124header.add(H2, VALUE);125header.add(badHeader, null);126header.prepend(fakeRequestLine, null);127ByteArrayOutputStream out = new ByteArrayOutputStream();128header.print(new PrintStream(out));129130if (!out.toString().equals(expectedHeaders)) {131throw new AssertionError("FAILED: expected: "132+ expectedHeaders + "\nReceived: " + out.toString());133} else {134System.out.println("PASSED: ::print returned correct "135+ "status line and headers:\n" + out.toString());136}137}138139// Test MessageHeader::print, ::toString, implicitly testing that140// MessageHeader::mergeHeader formats headers correctly for responses141static void testMessageHeaderMethods() throws IOException {142// {{inputString1, expectedToString1, expectedPrint1}, {...}}143String[][] strings = {144{"HTTP/1.1 200 OK\r\n"145+ "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"146+ "Connection: keep-alive\r\n"147+ "Host: 127.0.0.1:12345\r\n"148+ "User-agent: Java/12\r\n\r\nfoooo",149"pairs: {null: HTTP/1.1 200 OK}"150+ "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}"151+ "{Connection: keep-alive}"152+ "{Host: 127.0.0.1:12345}"153+ "{User-agent: Java/12}",154"Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"155+ "Connection: keep-alive\r\n"156+ "Host: 127.0.0.1:12345\r\n"157+ "User-agent: Java/12\r\n\r\n"},158{"HTTP/1.1 200 OK\r\n"159+ "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"160+ "Connection: keep-alive\r\n"161+ "Host: 127.0.0.1:12345\r\n"162+ "User-agent: Java/12\r\n"163+ "X-Header:\r\n\r\n",164"pairs: {null: HTTP/1.1 200 OK}"165+ "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}"166+ "{Connection: keep-alive}"167+ "{Host: 127.0.0.1:12345}"168+ "{User-agent: Java/12}"169+ "{X-Header: }",170"Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"171+ "Connection: keep-alive\r\n"172+ "Host: 127.0.0.1:12345\r\n"173+ "User-agent: Java/12\r\n"174+ "X-Header: \r\n\r\n"},175};176177System.out.println("Test custom message headers");178for (String[] s : strings) {179// Test MessageHeader::toString180MessageHeader header = new MessageHeader(181new ByteArrayInputStream(s[0].getBytes(ISO_8859_1)));182if (!header.toString().endsWith(s[1])) {183throw new AssertionError("FAILED: expected: "184+ s[1] + "\nReceived: " + header);185} else {186System.out.println("PASSED: ::toString returned correct "187+ "status line and headers:\n" + header);188}189190// Test MessageHeader::print191ByteArrayOutputStream out = new ByteArrayOutputStream();192header.print(new PrintStream(out));193if (!out.toString().equals(s[2])) {194throw new AssertionError("FAILED: expected: "195+ s[2] + "\nReceived: " + out.toString());196} else {197System.out.println("PASSED: ::print returned correct "198+ "status line and headers:\n" + out.toString());199}200}201}202203// Test methods URLConnection::getRequestProperties,204// ::getHeaderField, ::getHeaderFieldKey205static void testURLConnectionMethods() throws IOException {206HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);207urlConn.setRequestProperty(H1, "");208urlConn.setRequestProperty(H1, VALUE);209urlConn.setRequestProperty(H2, null); // Expected to contain ':' between key and value210Map<String, List<String>> props = urlConn.getRequestProperties();211Map<String, List<String>> expectedMap = Map.of(212H1, List.of(VALUE),213H2, Arrays.asList((String) null));214215// Test request properties216System.out.println("Client request properties");217StringBuilder sb = new StringBuilder();218props.forEach((k, v) -> sb.append(k + ": "219+ v.stream().collect(Collectors.joining()) + "\n"));220System.out.println(sb);221222if (!props.equals(expectedMap)) {223throw new AssertionError("Unexpected properties returned: "224+ props);225} else {226System.out.println("Properties returned as expected");227}228229// Test header fields230String headerField = urlConn.getHeaderField(0);231if (!headerField.contains("200 OK")) {232throw new AssertionError("Expected headerField[0]: status line. "233+ "Received: " + headerField);234} else {235System.out.println("PASSED: headerField[0] contains status line: "236+ headerField);237}238239String headerFieldKey = urlConn.getHeaderFieldKey(0);240if (headerFieldKey != null) {241throw new AssertionError("Expected headerFieldKey[0]: null. "242+ "Received: " + headerFieldKey);243} else {244System.out.println("PASSED: headerFieldKey[0] is null");245}246247// Check that test request headers are included with correct format248try (249BufferedReader in = new BufferedReader(250new InputStreamReader(urlConn.getInputStream()))251) {252if (!headers.keySet().contains(H1)) {253throw new AssertionError("Expected key not found: "254+ H1 + ": " + VALUE);255} else if (!headers.get(H1).equals(List.of(VALUE))) {256throw new AssertionError("Unexpected key-value pair: "257+ H1 + ": " + headers.get(H1));258} else {259System.out.println("PASSED: " + H1 + " included in request headers");260}261262if (!headers.keySet().contains(H2)) {263throw new AssertionError("Expected key not found: "264+ H2 + ": ");265// Check that empty list is returned266} else if (!headers.get(H2).equals(List.of(""))) {267throw new AssertionError("Unexpected key-value pair: "268+ H2 + ": " + headers.get(H2));269} else {270System.out.println("PASSED: " + H2 + " included in request headers");271}272273String inputLine;274while ((inputLine = in.readLine()) != null) {275System.out.println(inputLine);276}277}278}279}280281282