io.helidon.common.http.Content Maven / Gradle / Ivy
/*
* Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.common.http;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;
import java.util.function.Predicate;
import io.helidon.common.reactive.Flow;
/**
* Represents an HTTP entity as a {@link Flow.Publisher publisher} of {@link DataChunk chunks} with specific
* features.
* Default publisher contract
* Default publisher accepts only single subscriber. Other subscribers receives
* {@link Flow.Subscriber#onError(Throwable) onError()}.
*
* {@link DataChunk} provided by {@link Flow.Subscriber#onNext(Object) onNext()} method must be consumed in this
* method call. Buffer can be reused by network infrastructure as soon as {@code onNext()} method returns.
* This behavior can be inconvenient yet it helps to provide excellent performance.
*
*
Publisher Overwrite.
* It is possible to modify contract of the original publisher by registration of a new publisher using
* {@link #registerFilter(Function)} method. It can be used to wrap or replace previously registered (or default) publisher.
*
* Entity Readers
* It is possible to register function to convert publisher to {@link CompletionStage} of a single entity using
* {@link #registerReader(Class, Reader)} or {@link #registerReader(Predicate, Reader)} methods. It
* is then possible to use {@link #as(Class)} method to obtain such entity.
*/
public interface Content extends Flow.Publisher {
/**
* If possible, adds the given Subscriber to this publisher. This publisher is effectively
* either the original publisher
* or the last publisher registered by the method {@link #registerFilter(Function)}.
*
* Note that the original publisher allows only a single subscriber and requires the passed
* {@link DataChunk} in the {@link Flow.Subscriber#onNext(Object)} call
* to be consumed before the method completes as specified by the {@link Content Default Publisher Contract}.
*
* @param subscriber the subscriber
* @throws NullPointerException if subscriber is null
*/
@Override
void subscribe(Flow.Subscriber super DataChunk> subscriber);
/**
* Registers a filter that allows a control of the original publisher.
*
* The provided function is evaluated upon calling either of {@link #subscribe(Flow.Subscriber)}
* or {@link #as(Class)}.
* The first evaluation of the function transforms the original publisher to a new publisher.
* Any subsequent evaluation receives the publisher transformed by the last previously
* registered filter.
* It is up to the implementor of the given function to respect the contract of both the original
* publisher and the previously registered ones.
*
* @param function a function that transforms a given publisher (that is either the original
* publisher or the publisher transformed by the last previously registered filter).
*/
void registerFilter(Function, Flow.Publisher> function);
/**
* Registers a reader for a later use with an appropriate {@link #as(Class)} method call.
*
* The reader must transform the published byte buffers into a completion stage of the
* requested type.
*
* Upon calling {@link #as(Class)} a matching reader is searched in the same order as the
* readers were registered. If no matching reader is found, or when the function throws
* an exception, the resulting completion stage ends exceptionally.
*
* @param type the requested type the completion stage is be associated with.
* @param reader the reader as a function that transforms a publisher into completion stage.
* If an exception is thrown, the resulting completion stage of
* {@link #as(Class)} method call ends exceptionally.
* @param the requested type
*/
void registerReader(Class type, Reader reader);
/**
* Registers a reader for a later use with an appropriate {@link #as(Class)} method call.
*
* The reader must transform the published byte buffers into a completion stage of the
* requested type.
*
* Upon calling {@link #as(Class)} a matching reader is searched in the same order as the
* readers were registered. If no matching reader is found or when the predicate throws
* an exception, or when the function throws an exception, the resulting completion stage
* ends exceptionally.
*
* @param predicate the predicate that determines whether the registered reader can handle
* the requested type. If an exception is thrown, the resulting completion
* stage of {@link #as(Class)} method call ends exceptionally.
* @param reader the reader as a function that transforms a publisher into completion stage.
* If an exception is thrown, the resulting completion stage of
* {@link #as(Class)} method call ends exceptionally.
* @param the requested type
*/
void registerReader(Predicate> predicate, Reader reader);
/**
* Consumes and converts the request content into a completion stage of the requested type.
*
* The conversion requires an appropriate reader to be already registered
* (see {@link #registerReader(Predicate, Reader)}). If no such reader is found, the
* resulting completion stage ends exceptionally.
*
* @param type the requested type class
* @param the requested type
* @return a completion stage of the requested type
*/
CompletionStage as(Class type);
}