src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/OpeningHandshake.java
equal
deleted
inserted
replaced
26 package jdk.incubator.http.internal.websocket; |
26 package jdk.incubator.http.internal.websocket; |
27 |
27 |
28 import jdk.incubator.http.internal.common.MinimalFuture; |
28 import jdk.incubator.http.internal.common.MinimalFuture; |
29 |
29 |
30 import java.io.IOException; |
30 import java.io.IOException; |
|
31 import java.net.Proxy; |
31 import java.net.URI; |
32 import java.net.URI; |
32 import java.net.URISyntaxException; |
33 import java.net.URISyntaxException; |
33 import jdk.incubator.http.HttpClient; |
34 import jdk.incubator.http.HttpClient; |
34 import jdk.incubator.http.HttpClient.Version; |
35 import jdk.incubator.http.HttpClient.Version; |
35 import jdk.incubator.http.HttpHeaders; |
36 import jdk.incubator.http.HttpHeaders; |
38 import jdk.incubator.http.HttpResponse.BodyHandler; |
39 import jdk.incubator.http.HttpResponse.BodyHandler; |
39 import jdk.incubator.http.WebSocketHandshakeException; |
40 import jdk.incubator.http.WebSocketHandshakeException; |
40 import jdk.incubator.http.internal.common.Pair; |
41 import jdk.incubator.http.internal.common.Pair; |
41 |
42 |
42 import java.nio.charset.StandardCharsets; |
43 import java.nio.charset.StandardCharsets; |
|
44 import java.security.AccessController; |
43 import java.security.MessageDigest; |
45 import java.security.MessageDigest; |
44 import java.security.NoSuchAlgorithmException; |
46 import java.security.NoSuchAlgorithmException; |
|
47 import java.security.PrivilegedAction; |
45 import java.security.SecureRandom; |
48 import java.security.SecureRandom; |
46 import java.time.Duration; |
49 import java.time.Duration; |
47 import java.util.Base64; |
50 import java.util.Base64; |
48 import java.util.Collection; |
51 import java.util.Collection; |
49 import java.util.Collections; |
52 import java.util.Collections; |
97 |
100 |
98 private final HttpRequest request; |
101 private final HttpRequest request; |
99 private final Collection<String> subprotocols; |
102 private final Collection<String> subprotocols; |
100 private final String nonce; |
103 private final String nonce; |
101 |
104 |
102 OpeningHandshake(BuilderImpl b) { |
105 OpeningHandshake(BuilderImpl b, Proxy proxy) { |
103 this.client = b.getClient(); |
106 this.client = b.getClient(); |
104 URI httpURI = createRequestURI(b.getUri()); |
107 URI httpURI = createRequestURI(b.getUri()); |
105 HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(httpURI); |
108 HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(httpURI); |
106 Duration connectTimeout = b.getConnectTimeout(); |
109 Duration connectTimeout = b.getConnectTimeout(); |
107 if (connectTimeout != null) { |
110 if (connectTimeout != null) { |
128 this.request = requestBuilder.version(Version.HTTP_1_1).GET().build(); |
131 this.request = requestBuilder.version(Version.HTTP_1_1).GET().build(); |
129 WebSocketRequest r = (WebSocketRequest) this.request; |
132 WebSocketRequest r = (WebSocketRequest) this.request; |
130 r.isWebSocket(true); |
133 r.isWebSocket(true); |
131 r.setSystemHeader(HEADER_UPGRADE, "websocket"); |
134 r.setSystemHeader(HEADER_UPGRADE, "websocket"); |
132 r.setSystemHeader(HEADER_CONNECTION, "Upgrade"); |
135 r.setSystemHeader(HEADER_CONNECTION, "Upgrade"); |
|
136 r.setProxy(proxy); |
133 } |
137 } |
134 |
138 |
135 private static Collection<String> createRequestSubprotocols( |
139 private static Collection<String> createRequestSubprotocols( |
136 Collection<String> subprotocols) |
140 Collection<String> subprotocols) |
137 { |
141 { |
151 * Checks the given URI for being a WebSocket URI and translates it into a |
155 * Checks the given URI for being a WebSocket URI and translates it into a |
152 * target HTTP URI for the Opening Handshake. |
156 * target HTTP URI for the Opening Handshake. |
153 * |
157 * |
154 * https://tools.ietf.org/html/rfc6455#section-3 |
158 * https://tools.ietf.org/html/rfc6455#section-3 |
155 */ |
159 */ |
156 private static URI createRequestURI(URI uri) { |
160 static URI createRequestURI(URI uri) { |
157 // TODO: check permission for WebSocket URI and translate it into |
|
158 // http/https permission |
|
159 String s = uri.getScheme(); // The scheme might be null (i.e. undefined) |
161 String s = uri.getScheme(); // The scheme might be null (i.e. undefined) |
160 if (!("ws".equalsIgnoreCase(s) || "wss".equalsIgnoreCase(s)) |
162 if (!("ws".equalsIgnoreCase(s) || "wss".equalsIgnoreCase(s)) |
161 || uri.getFragment() != null) |
163 || uri.getFragment() != null) |
162 { |
164 { |
163 throw illegal("Bad URI: " + uri); |
165 throw illegal("Bad URI: " + uri); |
176 throw new InternalError(e); |
178 throw new InternalError(e); |
177 } |
179 } |
178 } |
180 } |
179 |
181 |
180 CompletableFuture<Result> send() { |
182 CompletableFuture<Result> send() { |
181 return client.sendAsync(this.request, BodyHandler.<Void>discard(null)) |
183 PrivilegedAction<CompletableFuture<Result>> pa = () -> |
182 .thenCompose(this::resultFrom); |
184 client.sendAsync(this.request, BodyHandler.<Void>discard(null)) |
|
185 .thenCompose(this::resultFrom); |
|
186 return AccessController.doPrivileged(pa); |
183 } |
187 } |
184 |
188 |
185 /* |
189 /* |
186 * The result of the opening handshake. |
190 * The result of the opening handshake. |
187 */ |
191 */ |
245 String x = this.nonce + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
249 String x = this.nonce + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
246 this.sha1.update(x.getBytes(StandardCharsets.ISO_8859_1)); |
250 this.sha1.update(x.getBytes(StandardCharsets.ISO_8859_1)); |
247 String expected = Base64.getEncoder().encodeToString(this.sha1.digest()); |
251 String expected = Base64.getEncoder().encodeToString(this.sha1.digest()); |
248 String actual = requireSingle(headers, HEADER_ACCEPT); |
252 String actual = requireSingle(headers, HEADER_ACCEPT); |
249 if (!actual.trim().equals(expected)) { |
253 if (!actual.trim().equals(expected)) { |
250 throw checkFailed("Bad " + HEADER_ACCEPT); |
254 throw checkFailed("Bad " + HEADER_ACCEPT + ", expected:[" |
|
255 + expected + "] ,got:[" + actual.trim() + "]"); |
251 } |
256 } |
252 String subprotocol = checkAndReturnSubprotocol(headers); |
257 String subprotocol = checkAndReturnSubprotocol(headers); |
253 RawChannel channel = ((RawChannel.Provider) response).rawChannel(); |
258 RawChannel channel = ((RawChannel.Provider) response).rawChannel(); |
254 return new Result(subprotocol, channel); |
259 return new Result(subprotocol, channel); |
255 } |
260 } |