22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.incubator.http;
27
28 import java.io.IOException;
29 import java.io.UncheckedIOException;
30 import java.net.URI;
31 import jdk.incubator.http.ResponseProcessors.MultiFile;
32 import jdk.incubator.http.ResponseProcessors.MultiProcessorImpl;
33 import static jdk.incubator.http.internal.common.Utils.unchecked;
34 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
35 import java.nio.ByteBuffer;
36 import java.nio.charset.Charset;
37 import java.nio.charset.StandardCharsets;
38 import java.nio.file.OpenOption;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
41 import java.nio.file.StandardOpenOption;
42 import java.util.Map;
43 import java.util.Optional;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.CompletionStage;
46 import java.util.concurrent.Flow;
47 import java.util.function.Consumer;
48 import java.util.function.Function;
49 import javax.net.ssl.SSLParameters;
50
51 /**
52 * Represents a response to a {@link HttpRequest}.
53 * {@Incubating}
54 *
55 * <p>A {@code HttpResponse} is available when the response status code and
56 * headers have been received, and typically after the response body has also
57 * been received. This depends on the response body handler provided when
58 * sending the request. In all cases, the response body handler is invoked
59 * before the body is read. This gives applications an opportunity to decide
60 * how to handle the body.
61 *
253 * {@link BodyProcessor BodyProcessor}{@code <String>} obtained from
254 * {@link BodyProcessor#asString(java.nio.charset.Charset)
255 * BodyProcessor.asString(Charset)}. If a charset is provided, the
256 * body is decoded using it. If charset is {@code null} then the processor
257 * tries to determine the character set from the {@code Content-encoding}
258 * header. If that charset is not supported then
259 * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
260 *
261 * @param charset the name of the charset to interpret the body as. If
262 * {@code null} then charset determined from Content-encoding header
263 * @return a response body handler
264 */
265 public static BodyHandler<String> asString(Charset charset) {
266 return (status, headers) -> {
267 if (charset != null) {
268 return BodyProcessor.asString(charset);
269 }
270 return BodyProcessor.asString(charsetFrom(headers));
271 };
272 }
273
274
275 /**
276 * Returns a {@code BodyHandler<Path>} that returns a
277 * {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
278 * {@link BodyProcessor#asFile(Path) BodyProcessor.asFile(Path)}.
279 * <p>
280 * When the {@code HttpResponse} object is returned, the body has been completely
281 * written to the file, and {@link #body()} returns a reference to its
282 * {@link Path}.
283 *
284 * @param file the file to store the body in
285 * @return a response body handler
286 */
287 public static BodyHandler<Path> asFile(Path file) {
288 return (status, headers) -> BodyProcessor.asFile(file);
289 }
290
291 /**
292 * Returns a {@code BodyHandler<Path>} that returns a
386 * BodyProcessor.asString(Charset)}. The body is
387 * decoded using the character set specified in
388 * the {@code Content-encoding} response header. If there is no such
389 * header, or the character set is not supported, then
390 * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
391 * <p>
392 * When the {@code HttpResponse} object is returned, the body has been completely
393 * written to the string.
394 *
395 * @return a response body handler
396 */
397 public static BodyHandler<String> asString() {
398 return (status, headers) -> BodyProcessor.asString(charsetFrom(headers));
399 }
400 }
401
402 /**
403 * A processor for response bodies.
404 * {@Incubating}
405 * <p>
406 * The object acts as a {@link Flow.Subscriber}<{@link ByteBuffer}> to
407 * the HTTP client implementation which publishes ByteBuffers containing the
408 * response body. The processor converts the incoming buffers of data to
409 * some user-defined object type {@code T}.
410 * <p>
411 * The {@link #getBody()} method returns a {@link CompletionStage}{@code <T>}
412 * that provides the response body object. The {@code CompletionStage} must
413 * be obtainable at any time. When it completes depends on the nature
414 * of type {@code T}. In many cases, when {@code T} represents the entire body after being
415 * read then it completes after the body has been read. If {@code T} is a streaming
416 * type such as {@link java.io.InputStream} then it completes before the
417 * body has been read, because the calling code uses it to consume the data.
418 *
419 * @param <T> the response body type
420 */
421 public interface BodyProcessor<T>
422 extends Flow.Subscriber<ByteBuffer> {
423
424 /**
425 * Returns a {@code CompletionStage} which when completed will return the
426 * response body object.
427 *
428 * @return a CompletionStage for the response body
429 */
430 public CompletionStage<T> getBody();
431
432 /**
433 * Returns a body processor which stores the response body as a {@code
434 * String} converted using the given {@code Charset}.
435 * <p>
436 * The {@link HttpResponse} using this processor is available after the
437 * entire response has been read.
438 *
439 * @param charset the character set to convert the String with
440 * @return a body processor
441 */
442 public static BodyProcessor<String> asString(Charset charset) {
443 return new ResponseProcessors.ByteArrayProcessor<>(
444 bytes -> new String(bytes, charset)
445 );
446 }
447
448 /**
449 * Returns a {@code BodyProcessor} which stores the response body as a
450 * byte array.
451 * <p>
452 * The {@link HttpResponse} using this processor is available after the
453 * entire response has been read.
454 *
455 * @return a body processor
456 */
457 public static BodyProcessor<byte[]> asByteArray() {
458 return new ResponseProcessors.ByteArrayProcessor<>(
459 Function.identity() // no conversion
460 );
461 }
462
463 /**
464 * Returns a {@code BodyProcessor} which stores the response body in a
465 * file opened with the given options and name. The file will be opened
466 * with the given options using
467 * {@link java.nio.channels.FileChannel#open(java.nio.file.Path,java.nio.file.OpenOption...)
468 * FileChannel.open} just before the body is read. Any exception thrown will be returned
|
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.incubator.http;
27
28 import java.io.IOException;
29 import java.io.UncheckedIOException;
30 import java.net.URI;
31 import jdk.incubator.http.ResponseProcessors.MultiFile;
32 import jdk.incubator.http.ResponseProcessors.MultiProcessorImpl;
33 import static jdk.incubator.http.internal.common.Utils.unchecked;
34 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
35 import java.nio.ByteBuffer;
36 import java.nio.charset.Charset;
37 import java.nio.charset.StandardCharsets;
38 import java.nio.file.OpenOption;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
41 import java.nio.file.StandardOpenOption;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Optional;
45 import java.util.concurrent.CompletableFuture;
46 import java.util.concurrent.CompletionStage;
47 import java.util.concurrent.Flow;
48 import java.util.function.Consumer;
49 import java.util.function.Function;
50 import javax.net.ssl.SSLParameters;
51
52 /**
53 * Represents a response to a {@link HttpRequest}.
54 * {@Incubating}
55 *
56 * <p>A {@code HttpResponse} is available when the response status code and
57 * headers have been received, and typically after the response body has also
58 * been received. This depends on the response body handler provided when
59 * sending the request. In all cases, the response body handler is invoked
60 * before the body is read. This gives applications an opportunity to decide
61 * how to handle the body.
62 *
254 * {@link BodyProcessor BodyProcessor}{@code <String>} obtained from
255 * {@link BodyProcessor#asString(java.nio.charset.Charset)
256 * BodyProcessor.asString(Charset)}. If a charset is provided, the
257 * body is decoded using it. If charset is {@code null} then the processor
258 * tries to determine the character set from the {@code Content-encoding}
259 * header. If that charset is not supported then
260 * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
261 *
262 * @param charset the name of the charset to interpret the body as. If
263 * {@code null} then charset determined from Content-encoding header
264 * @return a response body handler
265 */
266 public static BodyHandler<String> asString(Charset charset) {
267 return (status, headers) -> {
268 if (charset != null) {
269 return BodyProcessor.asString(charset);
270 }
271 return BodyProcessor.asString(charsetFrom(headers));
272 };
273 }
274 /**
275 * Returns a {@code BodyHandler} which returns {@linkplain
276 * BodyProcessor#buffering(BodyProcessor,long) buffering BodyProcessors} that
277 * buffer data before delivering it to the processors created by the given
278 * {@code downstream} handler. These {@code BodyProcessor}
279 * instances are created by calling
280 * {@link BodyProcessor#buffering(BodyProcessor,long) BodyProcessor.buffering()} with
281 * a processor obtained from the {@code downstream} handler and
282 * the {@code buffersize} parameter supplied to this call.
283 *
284 * @param downstream the downstream handler from the returned handler
285 * @param buffersize the buffersize parameter passed to {@link BodyProcessor#buffering(BodyProcessor,long)
286 * BodyProcessor.buffering()}
287 * @return a body handler
288 */
289 public static <T> BodyHandler<T> buffering(BodyHandler<T> downstream, long buffersize) {
290 return new BufferingHandler<>(downstream, buffersize);
291 }
292
293
294 /**
295 * Returns a {@code BodyHandler<Path>} that returns a
296 * {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
297 * {@link BodyProcessor#asFile(Path) BodyProcessor.asFile(Path)}.
298 * <p>
299 * When the {@code HttpResponse} object is returned, the body has been completely
300 * written to the file, and {@link #body()} returns a reference to its
301 * {@link Path}.
302 *
303 * @param file the file to store the body in
304 * @return a response body handler
305 */
306 public static BodyHandler<Path> asFile(Path file) {
307 return (status, headers) -> BodyProcessor.asFile(file);
308 }
309
310 /**
311 * Returns a {@code BodyHandler<Path>} that returns a
405 * BodyProcessor.asString(Charset)}. The body is
406 * decoded using the character set specified in
407 * the {@code Content-encoding} response header. If there is no such
408 * header, or the character set is not supported, then
409 * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
410 * <p>
411 * When the {@code HttpResponse} object is returned, the body has been completely
412 * written to the string.
413 *
414 * @return a response body handler
415 */
416 public static BodyHandler<String> asString() {
417 return (status, headers) -> BodyProcessor.asString(charsetFrom(headers));
418 }
419 }
420
421 /**
422 * A processor for response bodies.
423 * {@Incubating}
424 * <p>
425 * The object acts as a {@link Flow.Subscriber}<{@link List}<{@link
426 * ByteBuffer}>> to the HTTP client implementation which publishes ByteBuffers
427 * containing the response body. The processor converts the incoming buffers of data to
428 * some user-defined object type {@code T}.
429 * <p>
430 * The {@link #getBody()} method returns a {@link CompletionStage}{@code <T>}
431 * that provides the response body object. The {@code CompletionStage} must
432 * be obtainable at any time. When it completes depends on the nature
433 * of type {@code T}. In many cases, when {@code T} represents the entire body after being
434 * read then it completes after the body has been read. If {@code T} is a streaming
435 * type such as {@link java.io.InputStream} then it completes before the
436 * body has been read, because the calling code uses it to consume the data.
437 *
438 * @param <T> the response body type
439 */
440 public interface BodyProcessor<T>
441 extends Flow.Subscriber<List<ByteBuffer>> {
442
443 /**
444 * Returns a {@code CompletionStage} which when completed will return the
445 * response body object.
446 *
447 * @return a CompletionStage for the response body
448 */
449 public CompletionStage<T> getBody();
450
451 /**
452 * Returns a body processor which stores the response body as a {@code
453 * String} converted using the given {@code Charset}.
454 * <p>
455 * The {@link HttpResponse} using this processor is available after the
456 * entire response has been read.
457 *
458 * @param charset the character set to convert the String with
459 * @return a body processor
460 */
461 public static BodyProcessor<String> asString(Charset charset) {
462 return new ResponseProcessors.ByteArrayProcessor<>(
463 bytes -> new String(bytes, charset)
464 );
465 }
466
467 /**
468 * Returns a {@code BodyProcessor} which buffers data before delivering
469 * it to the given downstream processor. The processor guarantees to deliver
470 * {@code buffersize} bytes of data in each call to {@link #onNext(Object) onNext}
471 * except for the final call, just before {@link #onComplete() onComplete}
472 * is called. The final call of {@code onNext} may contain fewer than
473 * {@code buffersize}
474 * bytes.
475 * <p>
476 * The returned processor delegates its {@link #getBody()} call to the
477 * down stream processor.
478 *
479 * @param downstream the downstream processor for the returned handler
480 * @param buffersize the number of bytes guaranteed to be returned in each
481 * call to onNext() except for the last call.
482 *
483 * @return a body processor
484 */
485 public static <T> BodyProcessor<T> buffering(BodyProcessor<T> downstream, long buffersize) {
486 return new BufferingProcessor<>(downstream, buffersize);
487 }
488
489 /**
490 * Returns a {@code BodyProcessor} which stores the response body as a
491 * byte array.
492 * <p>
493 * The {@link HttpResponse} using this processor is available after the
494 * entire response has been read.
495 *
496 * @return a body processor
497 */
498 public static BodyProcessor<byte[]> asByteArray() {
499 return new ResponseProcessors.ByteArrayProcessor<>(
500 Function.identity() // no conversion
501 );
502 }
503
504 /**
505 * Returns a {@code BodyProcessor} which stores the response body in a
506 * file opened with the given options and name. The file will be opened
507 * with the given options using
508 * {@link java.nio.channels.FileChannel#open(java.nio.file.Path,java.nio.file.OpenOption...)
509 * FileChannel.open} just before the body is read. Any exception thrown will be returned
|