/** * Jooby https://jooby.io * Apache License Version 2.0 https://jooby.io/LICENSE.txt * Copyright 2014 Edgar Espina */ package io.jooby; import io.jooby.exception.MissingValueException; import io.jooby.internal.ByteArrayBody; import io.jooby.internal.FileBody; import io.jooby.internal.InputStreamBody; import javax.annotation.Nonnull; import java.io.InputStream; import java.lang.reflect.Type; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.Set; /** * HTTP body value. Allows to access HTTP body as string, byte[], stream, etc.. * * HTTP body can be read it only once per request. Attempt to read more than one resulted in * unexpected behaviour. * * @author edgar * @since 2.0.0 */ public interface Body extends ValueNode { /** * HTTP body as string. * * @param charset Charset. * @return Body as string. */ default @Nonnull String value(@Nonnull Charset charset) { byte[] bytes = bytes(); if (bytes.length == 0) { throw new MissingValueException("body"); } return new String(bytes, charset); } /** * HTTP body as byte array. * * @return Body as byte array. */ @Nonnull byte[] bytes(); /** * True if body is on memory. False, indicates body is on file system. Body larger than * {@link ServerOptions#getMaxRequestSize()} will be dump to disk. * * @return True if body is on memory. False, indicates body is on file system. */ boolean isInMemory(); /** * Size in bytes. This is the same as Content-Length header. * * @return Size in bytes. This is the same as Content-Length header. */ long getSize(); /** * Body as readable channel. * * @return Body as readable channel. */ @Nonnull ReadableByteChannel channel(); /** * Body as input stream. * * @return Body as input stream. */ @Nonnull InputStream stream(); @Nonnull @Override default List toList(@Nonnull Class type) { return to(Reified.list(type).getType()); } default @Nonnull @Override List toList() { return Collections.singletonList(value()); } default @Nonnull @Override Set toSet() { return Collections.singleton(value()); } @Override default @Nonnull T to(@Nonnull Class type) { return to((Type) type); } /** * Convert this body into the given type. * * @param type Type to use. * @param Generic type. * @return Converted value. */ @Nonnull T to(@Nonnull Type type); /* ********************************************************************************************** * Factory methods: * ********************************************************************************************** */ /** * Empty body. * * @param ctx Current context. * @return Empty body. */ static @Nonnull Body empty(@Nonnull Context ctx) { return ByteArrayBody.empty(ctx); } /** * Creates a HTTP body from input stream. * * @param ctx Current context. * @param stream Input stream. * @param size Size in bytes or -1. * @return A new body. */ static @Nonnull Body of(@Nonnull Context ctx, @Nonnull InputStream stream, long size) { return new InputStreamBody(ctx, stream, size); } /** * Creates a HTTP body from byte array. * * @param ctx Current context. * @param bytes byte array. * @return A new body. */ static @Nonnull Body of(@Nonnull Context ctx, @Nonnull byte[] bytes) { return new ByteArrayBody(ctx, bytes); } /** * Creates a HTTP body from file. * * @param ctx Current context. * @param file File. * @return A new body. */ static @Nonnull Body of(@Nonnull Context ctx, @Nonnull Path file) { return new FileBody(ctx, file); } }