< prev index next >
1 /*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 */
24 package java.net.http;
25
26 import java.io.IOException;
27 import java.net.InetSocketAddress;
28 import java.net.ProxySelector;
29 import java.net.URI;
30 import java.net.http.HttpClient.Version;
31 import java.net.http.HttpResponse.MultiProcessor;
32 import java.util.concurrent.CompletableFuture;
33 import java.net.SocketPermission;
34 import java.security.AccessControlContext;
35 import java.security.AccessController;
36 import java.util.Set;
37 import static java.net.http.HttpRedirectImpl.getRedirects;
38 import java.util.Locale;
39
40 class HttpRequestImpl extends HttpRequest {
41
42 private final HttpHeadersImpl userHeaders;
43 private final HttpHeadersImpl systemHeaders;
44 private final URI uri;
45 private InetSocketAddress authority; // only used when URI not specified
46 private final String method;
47 private final HttpClientImpl client;
48 private final HttpRedirectImpl followRedirects;
49 private final ProxySelector proxy;
50 final BodyProcessor requestProcessor;
51 final boolean secure;
52 final boolean expectContinue;
53 private final java.net.http.HttpClient.Version version;
54 private boolean isWebSocket;
55 final MultiExchange exchange;
56 private boolean receiving;
57 private AccessControlContext acc;
58 private final long timeval;
59
60 public HttpRequestImpl(HttpClientImpl client,
61 String method,
62 HttpRequestBuilderImpl builder) {
63 this.client = client;
64 this.method = method == null? "GET" : method;
65 this.userHeaders = builder.headers() == null ?
66 new HttpHeadersImpl() : builder.headers();
67 dropDisallowedHeaders();
68 this.followRedirects = getRedirects(builder.followRedirects() == null ?
69 client.followRedirects() : builder.followRedirects());
70 this.systemHeaders = new HttpHeadersImpl();
71 this.uri = builder.uri();
72 this.proxy = builder.proxy();
73 this.expectContinue = builder.expectContinue();
74 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
75 this.version = builder.version();
76 if (builder.body() == null) {
77 this.requestProcessor = HttpRequest.noBody();
78 } else {
79 this.requestProcessor = builder.body();
80 }
81 this.exchange = new MultiExchange(this);
82 this.timeval = builder.timeval();
83 }
84
85 /** Creates a HttpRequestImpl using fields of an existing request impl. */
86 public HttpRequestImpl(URI uri,
87 HttpRequest request,
88 HttpClientImpl client,
89 String method,
90 HttpRequestImpl other) {
91 this.client = client;
92 this.method = method == null? "GET" : method;
93 this.userHeaders = other.userHeaders == null ?
94 new HttpHeadersImpl() : other.userHeaders;
95 dropDisallowedHeaders();
96 this.followRedirects = getRedirects(other.followRedirects() == null ?
97 client.followRedirects() : other.followRedirects());
98 this.systemHeaders = other.systemHeaders;
99 this.uri = uri;
100 this.expectContinue = other.expectContinue;
101 this.secure = other.secure;
102 this.requestProcessor = other.requestProcessor;
103 this.proxy = other.proxy;
104 this.version = other.version;
105 this.acc = other.acc;
106 this.exchange = new MultiExchange(this);
107 this.timeval = other.timeval;
108 }
109
110 /* used for creating CONNECT requests */
111 HttpRequestImpl(HttpClientImpl client,
112 String method,
113 InetSocketAddress authority) {
114 this.client = client;
115 this.method = method;
116 this.followRedirects = getRedirects(client.followRedirects());
117 this.systemHeaders = new HttpHeadersImpl();
118 this.userHeaders = new HttpHeadersImpl();
119 this.uri = null;
120 this.proxy = null;
121 this.requestProcessor = HttpRequest.noBody();
122 this.version = java.net.http.HttpClient.Version.HTTP_1_1;
123 this.authority = authority;
124 this.secure = false;
125 this.expectContinue = false;
126 this.exchange = new MultiExchange(this);
127 this.timeval = 0; // block TODO: fix
128 }
129
130 @Override
131 public HttpClientImpl client() {
132 return client;
133 }
134
135
136 @Override
137 public String toString() {
138 return (uri == null ? "" : uri.toString()) + "/" + method + "("
139 + hashCode() + ")";
140 }
141
142 @Override
143 public HttpHeaders headers() {
144 userHeaders.makeUnmodifiable();
145 return userHeaders;
146 }
147
148 InetSocketAddress authority() { return authority; }
149
150 void setH2Upgrade() {
151 Http2ClientImpl h2client = client.client2();
152 systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
153 systemHeaders.setHeader("Upgrade", "h2c");
154 systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
155 }
156
157 private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
158 "authorization", "connection", "cookie", "content-length",
159 "date", "expect", "from", "host", "origin", "proxy-authorization",
160 "referer", "user-agent", "upgrade", "via", "warning");
161
162
163 // we silently drop headers that are disallowed
164 private void dropDisallowedHeaders() {
165 Set<String> hdrnames = userHeaders.directMap().keySet();
166
167 hdrnames.removeIf((s) ->
168 DISALLOWED_HEADERS_SET.contains(s.toLowerCase())
169 );
170 }
171
172 private synchronized void receiving() {
173 if (receiving) {
174 throw new IllegalStateException("already receiving response");
175 }
176 receiving = true;
177 }
178
179 /*
180 * Response filters may result in a new HttpRequestImpl being created
181 * (but still associated with the same API HttpRequest) and the process
182 * is repeated.
183 */
184 @Override
185 public HttpResponse response() throws IOException, InterruptedException {
186 receiving(); // TODO: update docs
187 if (System.getSecurityManager() != null) {
188 acc = AccessController.getContext();
189 }
190 return exchange.response();
191 }
192
193 @Override
194 public synchronized CompletableFuture<HttpResponse> responseAsync() {
195 receiving(); // TODO: update docs
196 if (System.getSecurityManager() != null) {
197 acc = AccessController.getContext();
198 }
199 return exchange.responseAsync(null)
200 .thenApply((r) -> (HttpResponse)r);
201 }
202
203 public <U> CompletableFuture<U>
204 sendAsyncMulti(HttpResponse.MultiProcessor<U> rspproc) {
205 // To change body of generated methods, choose Tools | Templates.
206 throw new UnsupportedOperationException("Not supported yet.");
207 }
208
209 @Override
210 public boolean expectContinue() { return expectContinue; }
211
212 public boolean requestHttp2() {
213 return version.equals(HttpClient.Version.HTTP_2);
214 //return client.getHttp2Allowed();
215 }
216
217 AccessControlContext getAccessControlContext() { return acc; }
218
219 InetSocketAddress proxy() {
220 ProxySelector ps = this.proxy;
221 if (ps == null) {
222 ps = client.proxy().orElse(null);
223 }
224 if (ps == null || method.equalsIgnoreCase("CONNECT")) {
225 return null;
226 }
227 return (InetSocketAddress)ps.select(uri).get(0).address();
228 }
229
230 boolean secure() { return secure; }
231
232 void isWebSocket(boolean is) {
233 isWebSocket = is;
234 }
235
236 boolean isWebSocket() {
237 return isWebSocket;
238 }
239
240 /** Returns the follow-redirects setting for this request. */
241 @Override
242 public java.net.http.HttpClient.Redirect followRedirects() {
243 return getRedirects(followRedirects);
244 }
245
246 HttpRedirectImpl followRedirectsImpl() { return followRedirects; }
247
248 /**
249 * Returns the request method for this request. If not set explicitly,
250 * the default method for any request is "GET".
251 */
252 @Override
253 public String method() { return method; }
254
255 @Override
256 public URI uri() { return uri; }
257
258 HttpHeadersImpl getUserHeaders() { return userHeaders; }
259
260 HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
261
262 HttpClientImpl getClient() { return client; }
263
264 BodyProcessor requestProcessor() { return requestProcessor; }
265
266 @Override
267 public Version version() { return version; }
268
269 void addSystemHeader(String name, String value) {
270 systemHeaders.addHeader(name, value);
271 }
272
273 void setSystemHeader(String name, String value) {
274 systemHeaders.setHeader(name, value);
275 }
276
277 long timeval() { return timeval; }
278
279 @Override
280 public <U> CompletableFuture<U>
281 multiResponseAsync(MultiProcessor<U> rspproc) {
282 //To change body of generated methods, choose Tools | Templates.
283 throw new UnsupportedOperationException("Not supported yet.");
284 }
285 }
< prev index next >