166 */ |
166 */ |
167 public HttpClient.Version version(); |
167 public HttpClient.Version version(); |
168 |
168 |
169 |
169 |
170 /** |
170 /** |
|
171 * Initial response information supplied to a {@link BodyHandler} when a |
|
172 * response is initially received and before the body is processed. |
|
173 */ |
|
174 public interface ResponseInfo { |
|
175 /** |
|
176 * Provides the response status code |
|
177 * @return the response status code |
|
178 */ |
|
179 public int statusCode(); |
|
180 |
|
181 /** |
|
182 * Provides the response headers |
|
183 * @return the response headers |
|
184 */ |
|
185 public HttpHeaders headers(); |
|
186 |
|
187 /** |
|
188 * Provides the response protocol version |
|
189 * @return the response protocol version |
|
190 */ |
|
191 public HttpClient.Version version(); |
|
192 } |
|
193 |
|
194 /** |
171 * A handler for response bodies. The class {@link BodyHandlers BodyHandlers} |
195 * A handler for response bodies. The class {@link BodyHandlers BodyHandlers} |
172 * provides implementations of many common body handlers. |
196 * provides implementations of many common body handlers. |
173 * |
197 * |
174 * <p> The {@code BodyHandler} interface allows inspection of the response |
198 * <p> The {@code BodyHandler} interface allows inspection of the response |
175 * code and headers, before the actual response body is received, and is |
199 * code and headers, before the actual response body is received, and is |
176 * responsible for creating the response {@link BodySubscriber |
200 * responsible for creating the response {@link BodySubscriber |
177 * BodySubscriber}. The {@code BodySubscriber} consumes the actual response |
201 * BodySubscriber}. The {@code BodySubscriber} consumes the actual response |
178 * body bytes and, typically, converts them into a higher-level Java type. |
202 * body bytes and, typically, converts them into a higher-level Java type. |
179 * |
203 * |
180 * <p> A {@code BodyHandler} is a function that takes two parameters: the |
204 * <p> A {@code BodyHandler} is a function that takes a {@link ResponseInfo} |
181 * response status code and the response headers; and which returns a |
205 * object; and which returns a |
182 * {@code BodySubscriber}. The {@code BodyHandler} is invoked when the |
206 * {@code BodySubscriber}. The {@code BodyHandler} is invoked when the |
183 * response status code and headers are available, but before the response |
207 * response status code and headers are available, but before the response |
184 * body bytes are received. |
208 * body bytes are received. |
185 * |
209 * |
186 * <p> The following example uses one of the {@linkplain BodyHandlers |
210 * <p> The following example uses one of the {@linkplain BodyHandlers |
201 * <p> In the second example, the function returns a different subscriber |
225 * <p> In the second example, the function returns a different subscriber |
202 * depending on the status code. |
226 * depending on the status code. |
203 * <pre>{@code HttpRequest request = HttpRequest.newBuilder() |
227 * <pre>{@code HttpRequest request = HttpRequest.newBuilder() |
204 * .uri(URI.create("http://www.foo.com/")) |
228 * .uri(URI.create("http://www.foo.com/")) |
205 * .build(); |
229 * .build(); |
206 * BodyHandler<Path> bodyHandler = (status, headers) -> status == 200 |
230 * BodyHandler<Path> bodyHandler = (rspInfo) -> rspInfo.statusCode() == 200 |
207 * ? BodySubscribers.ofFile(Paths.get("/tmp/f")) |
231 * ? BodySubscribers.ofFile(Paths.get("/tmp/f")) |
208 * : BodySubscribers.replacing(Paths.get("/NULL")); |
232 * : BodySubscribers.replacing(Paths.get("/NULL")); |
209 * client.sendAsync(request, bodyHandler) |
233 * client.sendAsync(request, bodyHandler) |
210 * .thenApply(HttpResponse::body) |
234 * .thenApply(HttpResponse::body) |
211 * .thenAccept(System.out::println); }</pre> |
235 * .thenAccept(System.out::println); }</pre> |
226 * |
250 * |
227 * <p> The response body can be discarded using one of {@link |
251 * <p> The response body can be discarded using one of {@link |
228 * BodyHandlers#discarding() discarding} or {@link |
252 * BodyHandlers#discarding() discarding} or {@link |
229 * BodyHandlers#replacing(Object) replacing}. |
253 * BodyHandlers#replacing(Object) replacing}. |
230 * |
254 * |
231 * @param statusCode the HTTP status code received |
255 * @param responseInfo the response info. |
232 * @param responseHeaders the response headers received |
|
233 * @return a body subscriber |
256 * @return a body subscriber |
234 */ |
257 */ |
235 public BodySubscriber<T> apply(int statusCode, HttpHeaders responseHeaders); |
258 public BodySubscriber<T> apply(ResponseInfo responseInfo); |
236 } |
259 } |
237 |
260 |
238 /** |
261 /** |
239 * Implementations of {@link BodyHandler BodyHandler} that implement various |
262 * Implementations of {@link BodyHandler BodyHandler} that implement various |
240 * useful handlers, such as handling the response body as a String, or |
263 * useful handlers, such as handling the response body as a String, or |
296 * @return a response body handler |
319 * @return a response body handler |
297 */ |
320 */ |
298 public static BodyHandler<Void> |
321 public static BodyHandler<Void> |
299 fromSubscriber(Subscriber<? super List<ByteBuffer>> subscriber) { |
322 fromSubscriber(Subscriber<? super List<ByteBuffer>> subscriber) { |
300 Objects.requireNonNull(subscriber); |
323 Objects.requireNonNull(subscriber); |
301 return (status, headers) -> BodySubscribers.fromSubscriber(subscriber, |
324 return (responseInfo) -> BodySubscribers.fromSubscriber(subscriber, |
302 s -> null); |
325 s -> null); |
303 } |
326 } |
304 |
327 |
305 /** |
328 /** |
306 * Returns a response body handler that returns a {@link BodySubscriber |
329 * Returns a response body handler that returns a {@link BodySubscriber |
330 */ |
353 */ |
331 public static <S extends Subscriber<? super List<ByteBuffer>>,T> BodyHandler<T> |
354 public static <S extends Subscriber<? super List<ByteBuffer>>,T> BodyHandler<T> |
332 fromSubscriber(S subscriber, Function<? super S,? extends T> finisher) { |
355 fromSubscriber(S subscriber, Function<? super S,? extends T> finisher) { |
333 Objects.requireNonNull(subscriber); |
356 Objects.requireNonNull(subscriber); |
334 Objects.requireNonNull(finisher); |
357 Objects.requireNonNull(finisher); |
335 return (status, headers) -> BodySubscribers.fromSubscriber(subscriber, |
358 return (responseInfo) -> BodySubscribers.fromSubscriber(subscriber, |
336 finisher); |
359 finisher); |
337 } |
360 } |
338 |
361 |
339 /** |
362 /** |
340 * Returns a response body handler that returns a {@link BodySubscriber |
363 * Returns a response body handler that returns a {@link BodySubscriber |
372 * @return a response body handler |
395 * @return a response body handler |
373 */ |
396 */ |
374 public static BodyHandler<Void> |
397 public static BodyHandler<Void> |
375 fromLineSubscriber(Subscriber<? super String> subscriber) { |
398 fromLineSubscriber(Subscriber<? super String> subscriber) { |
376 Objects.requireNonNull(subscriber); |
399 Objects.requireNonNull(subscriber); |
377 return (status, headers) -> |
400 return (responseInfo) -> |
378 BodySubscribers.fromLineSubscriber(subscriber, |
401 BodySubscribers.fromLineSubscriber(subscriber, |
379 s -> null, |
402 s -> null, |
380 charsetFrom(headers), |
403 charsetFrom(responseInfo.headers()), |
381 null); |
404 null); |
382 } |
405 } |
383 |
406 |
384 /** |
407 /** |
385 * Returns a response body handler that returns a {@link BodySubscriber |
408 * Returns a response body handler that returns a {@link BodySubscriber |
429 Objects.requireNonNull(subscriber); |
452 Objects.requireNonNull(subscriber); |
430 Objects.requireNonNull(finisher); |
453 Objects.requireNonNull(finisher); |
431 // implicit null check |
454 // implicit null check |
432 if (lineSeparator != null && lineSeparator.isEmpty()) |
455 if (lineSeparator != null && lineSeparator.isEmpty()) |
433 throw new IllegalArgumentException("empty line separator"); |
456 throw new IllegalArgumentException("empty line separator"); |
434 return (status, headers) -> |
457 return (responseInfo) -> |
435 BodySubscribers.fromLineSubscriber(subscriber, |
458 BodySubscribers.fromLineSubscriber(subscriber, |
436 finisher, |
459 finisher, |
437 charsetFrom(headers), |
460 charsetFrom(responseInfo.headers()), |
438 lineSeparator); |
461 lineSeparator); |
439 } |
462 } |
440 |
463 |
441 /** |
464 /** |
442 * Returns a response body handler that discards the response body. |
465 * Returns a response body handler that discards the response body. |
443 * |
466 * |
444 * @return a response body handler |
467 * @return a response body handler |
445 */ |
468 */ |
446 public static BodyHandler<Void> discarding() { |
469 public static BodyHandler<Void> discarding() { |
447 return (status, headers) -> BodySubscribers.discarding(); |
470 return (responseInfo) -> BodySubscribers.discarding(); |
448 } |
471 } |
449 |
472 |
450 /** |
473 /** |
451 * Returns a response body handler that returns the given replacement |
474 * Returns a response body handler that returns the given replacement |
452 * value, after discarding the response body. |
475 * value, after discarding the response body. |
454 * @param <U> the response body type |
477 * @param <U> the response body type |
455 * @param value the value of U to return as the body, may be {@code null} |
478 * @param value the value of U to return as the body, may be {@code null} |
456 * @return a response body handler |
479 * @return a response body handler |
457 */ |
480 */ |
458 public static <U> BodyHandler<U> replacing(U value) { |
481 public static <U> BodyHandler<U> replacing(U value) { |
459 return (status, headers) -> BodySubscribers.replacing(value); |
482 return (responseInfo) -> BodySubscribers.replacing(value); |
460 } |
483 } |
461 |
484 |
462 /** |
485 /** |
463 * Returns a {@code BodyHandler<String>} that returns a |
486 * Returns a {@code BodyHandler<String>} that returns a |
464 * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from |
487 * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from |
468 * @param charset the character set to convert the body with |
491 * @param charset the character set to convert the body with |
469 * @return a response body handler |
492 * @return a response body handler |
470 */ |
493 */ |
471 public static BodyHandler<String> ofString(Charset charset) { |
494 public static BodyHandler<String> ofString(Charset charset) { |
472 Objects.requireNonNull(charset); |
495 Objects.requireNonNull(charset); |
473 return (status, headers) -> BodySubscribers.ofString(charset); |
496 return (responseInfo) -> BodySubscribers.ofString(charset); |
474 } |
497 } |
475 |
498 |
476 /** |
499 /** |
477 * Returns a {@code BodyHandler<Path>} that returns a |
500 * Returns a {@code BodyHandler<Path>} that returns a |
478 * {@link BodySubscriber BodySubscriber}{@code <Path>} obtained from |
501 * {@link BodySubscriber BodySubscriber}{@code <Path>} obtained from |
586 * information. |
609 * information. |
587 * |
610 * |
588 * @return a response body handler |
611 * @return a response body handler |
589 */ |
612 */ |
590 public static BodyHandler<InputStream> ofInputStream() { |
613 public static BodyHandler<InputStream> ofInputStream() { |
591 return (status, headers) -> BodySubscribers.ofInputStream(); |
614 return (responseInfo) -> BodySubscribers.ofInputStream(); |
592 } |
615 } |
593 |
616 |
594 /** |
617 /** |
595 * Returns a {@code BodyHandler<Stream<String>>} that returns a |
618 * Returns a {@code BodyHandler<Stream<String>>} that returns a |
596 * {@link BodySubscriber BodySubscriber}{@code <Stream<String>>} obtained |
619 * {@link BodySubscriber BodySubscriber}{@code <Stream<String>>} obtained |
603 * not have been completely received. |
626 * not have been completely received. |
604 * |
627 * |
605 * @return a response body handler |
628 * @return a response body handler |
606 */ |
629 */ |
607 public static BodyHandler<Stream<String>> ofLines() { |
630 public static BodyHandler<Stream<String>> ofLines() { |
608 return (status, headers) -> |
631 return (responseInfo) -> |
609 BodySubscribers.ofLines(charsetFrom(headers)); |
632 BodySubscribers.ofLines(charsetFrom(responseInfo.headers())); |
610 } |
633 } |
611 |
634 |
612 /** |
635 /** |
613 * Returns a {@code BodyHandler<Void>} that returns a |
636 * Returns a {@code BodyHandler<Void>} that returns a |
614 * {@link BodySubscriber BodySubscriber}{@code <Void>} obtained from |
637 * {@link BodySubscriber BodySubscriber}{@code <Void>} obtained from |
627 * @return a response body handler |
650 * @return a response body handler |
628 */ |
651 */ |
629 public static BodyHandler<Void> |
652 public static BodyHandler<Void> |
630 ofByteArrayConsumer(Consumer<Optional<byte[]>> consumer) { |
653 ofByteArrayConsumer(Consumer<Optional<byte[]>> consumer) { |
631 Objects.requireNonNull(consumer); |
654 Objects.requireNonNull(consumer); |
632 return (status, headers) -> BodySubscribers.ofByteArrayConsumer(consumer); |
655 return (responseInfo) -> BodySubscribers.ofByteArrayConsumer(consumer); |
633 } |
656 } |
634 |
657 |
635 /** |
658 /** |
636 * Returns a {@code BodyHandler<byte[]>} that returns a |
659 * Returns a {@code BodyHandler<byte[]>} that returns a |
637 * {@link BodySubscriber BodySubscriber}<{@code byte[]}> obtained |
660 * {@link BodySubscriber BodySubscriber}<{@code byte[]}> obtained |
641 * been completely written to the byte array. |
664 * been completely written to the byte array. |
642 * |
665 * |
643 * @return a response body handler |
666 * @return a response body handler |
644 */ |
667 */ |
645 public static BodyHandler<byte[]> ofByteArray() { |
668 public static BodyHandler<byte[]> ofByteArray() { |
646 return (status, headers) -> BodySubscribers.ofByteArray(); |
669 return (responseInfo) -> BodySubscribers.ofByteArray(); |
647 } |
670 } |
648 |
671 |
649 /** |
672 /** |
650 * Returns a {@code BodyHandler<String>} that returns a |
673 * Returns a {@code BodyHandler<String>} that returns a |
651 * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from |
674 * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from |
659 * been completely written to the string. |
682 * been completely written to the string. |
660 * |
683 * |
661 * @return a response body handler |
684 * @return a response body handler |
662 */ |
685 */ |
663 public static BodyHandler<String> ofString() { |
686 public static BodyHandler<String> ofString() { |
664 return (status, headers) -> BodySubscribers.ofString(charsetFrom(headers)); |
687 return (responseInfo) -> BodySubscribers.ofString(charsetFrom(responseInfo.headers())); |
665 } |
688 } |
666 |
689 |
667 /** |
690 /** |
668 * Returns a {@code BodyHandler<Publisher<List<ByteBuffer>>>} that creates a |
691 * Returns a {@code BodyHandler<Publisher<List<ByteBuffer>>>} that creates a |
669 * {@link BodySubscriber BodySubscriber}{@code <Publisher<List<ByteBuffer>>>} |
692 * {@link BodySubscriber BodySubscriber}{@code <Publisher<List<ByteBuffer>>>} |
681 * information. |
704 * information. |
682 * |
705 * |
683 * @return a response body handler |
706 * @return a response body handler |
684 */ |
707 */ |
685 public static BodyHandler<Publisher<List<ByteBuffer>>> ofPublisher() { |
708 public static BodyHandler<Publisher<List<ByteBuffer>>> ofPublisher() { |
686 return (status, headers) -> BodySubscribers.ofPublisher(); |
709 return (responseInfo) -> BodySubscribers.ofPublisher(); |
687 } |
710 } |
688 |
711 |
689 /** |
712 /** |
690 * Returns a {@code BodyHandler} which, when invoked, returns a {@linkplain |
713 * Returns a {@code BodyHandler} which, when invoked, returns a {@linkplain |
691 * BodySubscribers#buffering(BodySubscriber,int) buffering BodySubscriber} |
714 * BodySubscribers#buffering(BodySubscriber,int) buffering BodySubscriber} |
705 public static <T> BodyHandler<T> buffering(BodyHandler<T> downstreamHandler, |
728 public static <T> BodyHandler<T> buffering(BodyHandler<T> downstreamHandler, |
706 int bufferSize) { |
729 int bufferSize) { |
707 Objects.requireNonNull(downstreamHandler); |
730 Objects.requireNonNull(downstreamHandler); |
708 if (bufferSize <= 0) |
731 if (bufferSize <= 0) |
709 throw new IllegalArgumentException("must be greater than 0"); |
732 throw new IllegalArgumentException("must be greater than 0"); |
710 return (status, headers) -> BodySubscribers |
733 return (responseInfo) -> BodySubscribers |
711 .buffering(downstreamHandler.apply(status, headers), |
734 .buffering(downstreamHandler.apply(responseInfo), |
712 bufferSize); |
735 bufferSize); |
713 } |
736 } |
714 } |
737 } |
715 |
738 |
716 /** |
739 /** |