1 /*
2 * Copyright (c) 2015, 2020, 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
246 return -1L;
247 }
248 if (responseCode == 101) {
249 // this is a h2c or websocket upgrade, contentlength must be zero
250 return 0L;
251 }
252 return -2L;
253 }
254 return clen;
255 }
256
257 /**
258 * Read up to MAX_IGNORE bytes discarding
259 */
260 public CompletableFuture<Void> ignoreBody(Executor executor) {
261 int clen = (int)headers.firstValueAsLong("Content-Length").orElse(-1);
262 if (clen == -1 || clen > MAX_IGNORE) {
263 connection.close();
264 return MinimalFuture.completedFuture(null); // not treating as error
265 } else {
266 return readBody(discarding(), !request.isWebSocket(), executor);
267 }
268 }
269
270 // Used for those response codes that have no body associated
271 public void nullBody(HttpResponse<T> resp, Throwable t) {
272 if (t != null) connection.close();
273 else {
274 return2Cache = !request.isWebSocket();
275 onFinished();
276 }
277 }
278
279 static final Flow.Subscription NOP = new Flow.Subscription() {
280 @Override
281 public void request(long n) { }
282 public void cancel() { }
283 };
284
285 /**
286 * The Http1AsyncReceiver ensures that all calls to
370 }
371 }
372 @Override
373 public void onNext(List<ByteBuffer> item) {
374 assert !completed.get();
375 userSubscriber.onNext(item);
376 }
377 @Override
378 public void onError(Throwable throwable) {
379 complete(throwable);
380 }
381 @Override
382 public void onComplete() {
383 complete(null);
384 }
385 }
386
387 public <U> CompletableFuture<U> readBody(HttpResponse.BodySubscriber<U> p,
388 boolean return2Cache,
389 Executor executor) {
390 if (debug.on()) {
391 debug.log("readBody: return2Cache: " + return2Cache);
392 if (request.isWebSocket() && return2Cache && connection != null) {
393 debug.log("websocket connection will be returned to cache: "
394 + connection.getClass() + "/" + connection );
395 }
396 }
397 assert !return2Cache || !request.isWebSocket();
398 this.return2Cache = return2Cache;
399 final Http1BodySubscriber<U> subscriber = new Http1BodySubscriber<>(p);
400
401 final CompletableFuture<U> cf = new MinimalFuture<>();
402
403 long clen0 = headers.firstValueAsLong("Content-Length").orElse(-1L);
404 final long clen = fixupContentLen(clen0);
405
406 // expect-continue reads headers and body twice.
407 // if we reach here, we must reset the headersReader state.
408 asyncReceiver.unsubscribe(headersReader);
409 headersReader.reset();
410 ClientRefCountTracker refCountTracker = new ClientRefCountTracker();
411
412 // We need to keep hold on the client facade until the
413 // tracker has been incremented.
414 connection.client().reference();
415 executor.execute(() -> {
416 try {
417 content = new ResponseContent(
|
1 /*
2 * Copyright (c) 2015, 2019, 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
246 return -1L;
247 }
248 if (responseCode == 101) {
249 // this is a h2c or websocket upgrade, contentlength must be zero
250 return 0L;
251 }
252 return -2L;
253 }
254 return clen;
255 }
256
257 /**
258 * Read up to MAX_IGNORE bytes discarding
259 */
260 public CompletableFuture<Void> ignoreBody(Executor executor) {
261 int clen = (int)headers.firstValueAsLong("Content-Length").orElse(-1);
262 if (clen == -1 || clen > MAX_IGNORE) {
263 connection.close();
264 return MinimalFuture.completedFuture(null); // not treating as error
265 } else {
266 return readBody(discarding(), true, executor);
267 }
268 }
269
270 // Used for those response codes that have no body associated
271 public void nullBody(HttpResponse<T> resp, Throwable t) {
272 if (t != null) connection.close();
273 else {
274 return2Cache = !request.isWebSocket();
275 onFinished();
276 }
277 }
278
279 static final Flow.Subscription NOP = new Flow.Subscription() {
280 @Override
281 public void request(long n) { }
282 public void cancel() { }
283 };
284
285 /**
286 * The Http1AsyncReceiver ensures that all calls to
370 }
371 }
372 @Override
373 public void onNext(List<ByteBuffer> item) {
374 assert !completed.get();
375 userSubscriber.onNext(item);
376 }
377 @Override
378 public void onError(Throwable throwable) {
379 complete(throwable);
380 }
381 @Override
382 public void onComplete() {
383 complete(null);
384 }
385 }
386
387 public <U> CompletableFuture<U> readBody(HttpResponse.BodySubscriber<U> p,
388 boolean return2Cache,
389 Executor executor) {
390 this.return2Cache = return2Cache;
391 final Http1BodySubscriber<U> subscriber = new Http1BodySubscriber<>(p);
392
393 final CompletableFuture<U> cf = new MinimalFuture<>();
394
395 long clen0 = headers.firstValueAsLong("Content-Length").orElse(-1L);
396 final long clen = fixupContentLen(clen0);
397
398 // expect-continue reads headers and body twice.
399 // if we reach here, we must reset the headersReader state.
400 asyncReceiver.unsubscribe(headersReader);
401 headersReader.reset();
402 ClientRefCountTracker refCountTracker = new ClientRefCountTracker();
403
404 // We need to keep hold on the client facade until the
405 // tracker has been incremented.
406 connection.client().reference();
407 executor.execute(() -> {
408 try {
409 content = new ResponseContent(
|