Search in sources :

Example 11 with DataChunk

use of io.helidon.common.http.DataChunk in project helidon by oracle.

the class HelidonEntity method submit.

/**
 * Convert Jersey {@code OutputStream} to an entity based on the client request use case and submits to the provided
 * {@code WebClientRequestBuilder}.
 * @param type the type of the Helidon entity.
 * @param requestContext Jersey {@link ClientRequest} providing the entity {@code OutputStream}.
 * @param requestBuilder Helidon {@code WebClientRequestBuilder} which is used to submit the entity
 * @param executorService {@link ExecutorService} that fills the entity instance for Helidon with data from Jersey
 *                      {@code OutputStream}.
 * @return Helidon Client response completion stage.
 */
static CompletionStage<WebClientResponse> submit(HelidonEntityType type, ClientRequest requestContext, WebClientRequestBuilder requestBuilder, ExecutorService executorService) {
    CompletionStage<WebClientResponse> stage = null;
    if (type != null) {
        final int bufferSize = requestContext.resolveProperty(ClientProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 8192);
        switch(type) {
            case BYTE_ARRAY_OUTPUT_STREAM:
                final ByteArrayOutputStream baos = new ByteArrayOutputStream(bufferSize);
                requestContext.setStreamProvider(contentLength -> baos);
                ((ProcessingRunnable) requestContext::writeEntity).run();
                stage = requestBuilder.submit(baos);
                break;
            case READABLE_BYTE_CHANNEL:
                final OutputStreamChannel channel = new OutputStreamChannel(bufferSize);
                requestContext.setStreamProvider(contentLength -> channel);
                executorService.execute((ProcessingRunnable) requestContext::writeEntity);
                stage = requestBuilder.submit(channel);
                break;
            case OUTPUT_STREAM_MULTI:
                final OutputStreamMulti publisher = IoMulti.outputStreamMulti();
                requestContext.setStreamProvider(contentLength -> publisher);
                executorService.execute((ProcessingRunnable) () -> {
                    requestContext.writeEntity();
                    publisher.close();
                });
                stage = requestBuilder.submit(Multi.create(publisher).map(DataChunk::create));
                break;
            default:
        }
    }
    return stage;
}
Also used : WebClientResponse(io.helidon.webclient.WebClientResponse) OutputStreamMulti(io.helidon.common.reactive.OutputStreamMulti) DataChunk(io.helidon.common.http.DataChunk) ByteArrayOutputStream(java.io.ByteArrayOutputStream)

Example 12 with DataChunk

use of io.helidon.common.http.DataChunk in project helidon by oracle.

the class FormParamsBodyReader method read.

@Override
@SuppressWarnings("unchecked")
public <U extends FormParams> Single<U> read(Flow.Publisher<DataChunk> publisher, GenericType<U> type, MessageBodyReaderContext context) {
    MediaType mediaType = context.contentType().orElseThrow();
    Charset charset = mediaType.charset().map(Charset::forName).orElse(StandardCharsets.UTF_8);
    Function<String, String> decoder = decoder(mediaType, charset);
    return (Single<U>) ContentReaders.readString(publisher, charset).map(formStr -> create(formStr, mediaType, decoder));
}
Also used : URLDecoder(java.net.URLDecoder) DataChunk(io.helidon.common.http.DataChunk) GenericType(io.helidon.common.GenericType) Function(java.util.function.Function) StandardCharsets(java.nio.charset.StandardCharsets) MediaType(io.helidon.common.http.MediaType) Matcher(java.util.regex.Matcher) Charset(java.nio.charset.Charset) Flow(java.util.concurrent.Flow) Map(java.util.Map) FormParams(io.helidon.common.http.FormParams) Single(io.helidon.common.reactive.Single) Pattern(java.util.regex.Pattern) Single(io.helidon.common.reactive.Single) MediaType(io.helidon.common.http.MediaType) Charset(java.nio.charset.Charset)

Example 13 with DataChunk

use of io.helidon.common.http.DataChunk in project helidon by oracle.

the class ContentWriters method writeStackTrace.

/**
 * Create a a publisher {@link DataChunk} with the given
 * {@link Throwable} / {@link Charset} and return a {@link Single}.
 *
 * @param throwable the {@link Throwable}
 * @param charset the charset to use to encode the stack trace
 * @return Single
 * @since 2.0.0
 */
public static Single<DataChunk> writeStackTrace(Throwable throwable, Charset charset) {
    final StringWriter stringWriter = new StringWriter();
    final PrintWriter printWriter = new PrintWriter(stringWriter);
    String stackTraceString = null;
    try {
        throwable.printStackTrace(printWriter);
        stackTraceString = stringWriter.toString();
    } finally {
        printWriter.close();
    }
    final Single<DataChunk> returnValue;
    if (stackTraceString.isEmpty()) {
        returnValue = Single.<DataChunk>empty();
    } else {
        returnValue = writeCharSequence(stackTraceString, charset);
    }
    return returnValue;
}
Also used : StringWriter(java.io.StringWriter) DataChunk(io.helidon.common.http.DataChunk) PrintWriter(java.io.PrintWriter)

Example 14 with DataChunk

use of io.helidon.common.http.DataChunk in project helidon by oracle.

the class MultiPartDecoderTest method testPartContentSubscriberThrottling.

@Test
public void testPartContentSubscriberThrottling() {
    String boundary = "boundary";
    final byte[] chunk1 = ("--" + boundary + "\n" + "Content-Id: part1\n" + "\n" + "body 1.aaaa\n").getBytes();
    final byte[] chunk2 = "body 1.bbbb\n".getBytes();
    final byte[] chunk3 = ("body 1.cccc\n" + "--" + boundary + "\n" + "Content-Id: part2\n" + "\n" + "This is the 2nd").getBytes();
    final byte[] chunk4 = ("body.\n" + "--" + boundary + "--").getBytes();
    final CountDownLatch latch = new CountDownLatch(3);
    Consumer<BodyPart> consumer = (part) -> {
        latch.countDown();
        if (latch.getCount() == 2) {
            assertThat(part.headers().values("Content-Id"), hasItems("part1"));
        }
        part.content().subscribe(new Subscriber<DataChunk>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(1);
            }

            @Override
            public void onNext(DataChunk item) {
                latch.countDown();
            }

            @Override
            public void onError(Throwable throwable) {
            }

            @Override
            public void onComplete() {
            }
        });
    };
    BodyPartSubscriber testSubscriber = new BodyPartSubscriber(SUBSCRIBER_TYPE.ONE_BY_ONE, consumer);
    partsPublisher(boundary, List.of(chunk1, chunk2, chunk3, chunk4)).subscribe(testSubscriber);
    waitOnLatchNegative(latch, "the 2nd part should not be processed");
    assertThat(latch.getCount(), is(equalTo(1L)));
    try {
        testSubscriber.complete.orTimeout(200, TimeUnit.MILLISECONDS).join();
        throw new IllegalStateException("Not expecting to make progress, unless the part is consumed");
    } catch (CompletionException e) {
        Throwable error = e.getCause();
        // This is the expected outcome - the testSubcriber is not making progress
        assertThat(error.getClass(), is(equalTo(TimeoutException.class)));
    }
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) Assertions.fail(org.junit.jupiter.api.Assertions.fail) CoreMatchers.hasItems(org.hamcrest.CoreMatchers.hasItems) Subscription(java.util.concurrent.Flow.Subscription) DataChunk(io.helidon.common.http.DataChunk) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) Publisher(java.util.concurrent.Flow.Publisher) Subscriber(java.util.concurrent.Flow.Subscriber) Matchers.equalTo(org.hamcrest.Matchers.equalTo) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Multi(io.helidon.common.reactive.Multi) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) CountDownLatch(java.util.concurrent.CountDownLatch) Subscriber(java.util.concurrent.Flow.Subscriber) CompletionException(java.util.concurrent.CompletionException) DataChunk(io.helidon.common.http.DataChunk) Subscription(java.util.concurrent.Flow.Subscription) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.jupiter.api.Test)

Example 15 with DataChunk

use of io.helidon.common.http.DataChunk in project helidon by oracle.

the class RequestContentSubscriber method sendData.

private void sendData(DataChunk data) {
    LOGGER.finest(() -> "(client reqID: " + requestId + ") Sending data chunk");
    DefaultHttpContent httpContent = new DefaultHttpContent(Unpooled.wrappedBuffer(data.data()));
    channel.write(true, httpContent, f -> f.addListener(future -> {
        data.release();
        subscription.request(1);
        LOGGER.finest(() -> "(client reqID: " + requestId + ") Data chunk sent with result: " + future.isSuccess());
    }).addListener(completeOnFailureListener("(client reqID: " + requestId + ") Failure when sending a content!")).addListener(ChannelFutureListener.CLOSE_ON_FAILURE));
}
Also used : HttpHeaderValues(io.netty.handler.codec.http.HttpHeaderValues) REQUEST_ID(io.helidon.webclient.WebClientRequestBuilderImpl.REQUEST_ID) DataChunk(io.helidon.common.http.DataChunk) Set(java.util.Set) HttpMethod(io.netty.handler.codec.http.HttpMethod) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) CompletableFuture(java.util.concurrent.CompletableFuture) Logger(java.util.logging.Logger) Unpooled(io.netty.buffer.Unpooled) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) Channel(io.netty.channel.Channel) DefaultHttpContent(io.netty.handler.codec.http.DefaultHttpContent) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) Flow(java.util.concurrent.Flow) ChannelFutureListener(io.netty.channel.ChannelFutureListener) HttpHeaderNames(io.netty.handler.codec.http.HttpHeaderNames) Http(io.helidon.common.http.Http) Future(io.netty.util.concurrent.Future) HttpUtil(io.netty.handler.codec.http.HttpUtil) DefaultHttpContent(io.netty.handler.codec.http.DefaultHttpContent)

Aggregations

DataChunk (io.helidon.common.http.DataChunk)43 Test (org.junit.jupiter.api.Test)18 Multi (io.helidon.common.reactive.Multi)12 Flow (java.util.concurrent.Flow)11 GenericType (io.helidon.common.GenericType)9 CompletableFuture (java.util.concurrent.CompletableFuture)9 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)9 Http (io.helidon.common.http.Http)8 Single (io.helidon.common.reactive.Single)8 ByteBuffer (java.nio.ByteBuffer)8 MediaType (io.helidon.common.http.MediaType)7 MessageBodyWriterContext (io.helidon.media.common.MessageBodyWriterContext)7 WebClient (io.helidon.webclient.WebClient)7 WebClientResponse (io.helidon.webclient.WebClientResponse)7 IOException (java.io.IOException)7 List (java.util.List)7 Optional (java.util.Optional)7 TimeUnit (java.util.concurrent.TimeUnit)7 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)7 Logger (java.util.logging.Logger)6