# HG changeset patch # User prappo # Date 1512575274 -10800 # Node ID 1da220f80a5d5ab91d1360c5633e9d6408999d37 # Parent 11a97b370db0e2e722d0425633658aaf8e96fc98 http-client-branch: (WebSocket) relaxed Opening Handshake constraints; originated from JDK-8191646 diff -r 11a97b370db0 -r 1da220f80a5d src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/OpeningHandshake.java --- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/OpeningHandshake.java Wed Dec 06 14:29:06 2017 +0000 +++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/OpeningHandshake.java Wed Dec 06 18:47:54 2017 +0300 @@ -25,7 +25,16 @@ package jdk.incubator.http.internal.websocket; +import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpClient.Version; +import jdk.incubator.http.HttpHeaders; +import jdk.incubator.http.HttpRequest; +import jdk.incubator.http.HttpResponse; +import jdk.incubator.http.HttpResponse.BodyHandler; +import jdk.incubator.http.WebSocketHandshakeException; import jdk.incubator.http.internal.common.MinimalFuture; +import jdk.incubator.http.internal.common.Pair; +import jdk.incubator.http.internal.common.Utils; import java.io.IOException; import java.net.InetSocketAddress; @@ -33,16 +42,6 @@ import java.net.ProxySelector; import java.net.URI; import java.net.URISyntaxException; -import jdk.incubator.http.HttpClient; -import jdk.incubator.http.HttpClient.Version; -import jdk.incubator.http.HttpHeaders; -import jdk.incubator.http.HttpRequest; -import jdk.incubator.http.HttpResponse; -import jdk.incubator.http.HttpResponse.BodyHandler; -import jdk.incubator.http.WebSocketHandshakeException; -import jdk.incubator.http.internal.common.Pair; -import jdk.incubator.http.internal.common.Utils; - import java.net.URLPermission; import java.nio.charset.StandardCharsets; import java.security.AccessController; @@ -77,6 +76,7 @@ private static final String HEADER_KEY = "Sec-WebSocket-Key"; private static final String HEADER_PROTOCOL = "Sec-WebSocket-Protocol"; private static final String HEADER_VERSION = "Sec-WebSocket-Version"; + private static final String VERSION = "13"; // WebSocket's lucky number private static final Set ILLEGAL_HEADERS; @@ -130,7 +130,7 @@ String p = this.subprotocols.stream().collect(Collectors.joining(", ")); requestBuilder.header(HEADER_PROTOCOL, p); } - requestBuilder.header(HEADER_VERSION, "13"); // WebSocket's lucky number + requestBuilder.header(HEADER_VERSION, VERSION); this.nonce = createNonce(); requestBuilder.header(HEADER_KEY, this.nonce); // Setting request version to HTTP/1.1 forcibly, since it's not possible @@ -249,7 +249,10 @@ if (!connection.equalsIgnoreCase("Upgrade")) { throw checkFailed("Bad response field: " + HEADER_CONNECTION); } - requireAbsent(headers, HEADER_VERSION); + Optional version = requireAtMostOne(headers, HEADER_VERSION); + if (version.isPresent() && !version.get().equals(VERSION)) { + throw checkFailed("Bad response field: " + HEADER_VERSION); + } requireAbsent(headers, HEADER_EXTENSIONS); String x = this.nonce + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; this.sha1.update(x.getBytes(StandardCharsets.ISO_8859_1)); @@ -293,6 +296,18 @@ } } + private static Optional requireAtMostOne(HttpHeaders responseHeaders, + String headerName) + { + List values = responseHeaders.allValues(headerName); + if (values.size() > 1) { + throw checkFailed(format("Response field '%s' multivalued: %s", + headerName, + stringOf(values))); + } + return values.stream().findFirst(); + } + private static String requireSingle(HttpHeaders responseHeaders, String headerName) {