pub struct PluginPipeline<P>(_);
Expand description

A wrapper struct for composing Plugins. It is used as input for the builder_with_plugins method on the generate service struct (e.g. PokemonService::builder_with_plugins).

Applying plugins in a sequence

You can use the push method to apply a new plugin after the ones that have already been registered.

use aws_smithy_http_server::plugin::PluginPipeline;

let pipeline = PluginPipeline::new().push(LoggingPlugin).push(MetricsPlugin);

The plugins’ runtime logic is executed in registration order. In our example above, LoggingPlugin would run first, while MetricsPlugin is executed last.

Wrapping the current plugin pipeline

From time to time, you might have a need to transform the entire pipeline that has been built so far - e.g. you only want to apply those plugins for a specific operation.

PluginPipeline is itself a Plugin: you can apply any transformation that expects a Plugin to an entire pipeline. In this case, we want to use filter_by_operation_name to limit the scope of the logging and metrics plugins to the CheckHealth operation:

use aws_smithy_http_server::plugin::{filter_by_operation_name, PluginPipeline};

// The logging and metrics plugins will only be applied to the `CheckHealth` operation.
let operation_specific_pipeline = filter_by_operation_name(
    PluginPipeline::new()
        .push(LoggingPlugin)
        .push(MetricsPlugin),
    |name| name == CheckHealth::NAME
);
let pipeline = PluginPipeline::new()
    .push(operation_specific_pipeline)
    // The auth plugin will be applied to all operations
    .push(AuthPlugin);

Concatenating two plugin pipelines

PluginPipeline is a good way to bundle together multiple plugins, ensuring they are all registered in the correct order.

Since PluginPipeline is itself a Plugin, you can use the push to append, at once, all the plugins in another pipeline to the current pipeline:

use aws_smithy_http_server::plugin::{IdentityPlugin, PluginPipeline, PluginStack};

pub fn get_bundled_pipeline() -> PluginPipeline<PluginStack<MetricsPlugin, PluginStack<LoggingPlugin, IdentityPlugin>>> {
    PluginPipeline::new().push(LoggingPlugin).push(MetricsPlugin)
}

let pipeline = PluginPipeline::new()
    .push(AuthPlugin)
    .push(get_bundled_pipeline());

Providing custom methods on PluginPipeline

You use an extension trait to add custom methods on PluginPipeline.

This is a simple example using AuthPlugin:

use aws_smithy_http_server::plugin::{PluginPipeline, PluginStack};

pub trait AuthPluginExt<CurrentPlugins> {
    fn with_auth(self) -> PluginPipeline<PluginStack<AuthPlugin, CurrentPlugins>>;
}

impl<CurrentPlugins> AuthPluginExt<CurrentPlugins> for PluginPipeline<CurrentPlugins> {
    fn with_auth(self) -> PluginPipeline<PluginStack<AuthPlugin, CurrentPlugins>> {
        self.push(AuthPlugin)
    }
}

let pipeline = PluginPipeline::new()
    .push(LoggingPlugin)
    // Our custom method!
    .with_auth();

Implementations§

source§

impl PluginPipeline<IdentityPlugin>

source

pub fn new() -> Self

Create an empty PluginPipeline.

You can use PluginPipeline::push to add plugins to it.

source§

impl<P> PluginPipeline<P>

source

pub fn push<NewPlugin>( self, new_plugin: NewPlugin ) -> PluginPipeline<PluginStack<NewPlugin, P>>

Apply a new plugin after the ones that have already been registered.

use aws_smithy_http_server::plugin::PluginPipeline;

let pipeline = PluginPipeline::new().push(LoggingPlugin).push(MetricsPlugin);

The plugins’ runtime logic is executed in registration order. In our example above, LoggingPlugin would run first, while MetricsPlugin is executed last.

Implementation notes

Plugins are applied to the underlying Operation in opposite order compared to their registration order. But most Plugin::map implementations desugar to appending a layer to Operation, usually via Operation::layer. As an example:

#[derive(Debug)]
pub struct PrintPlugin;

impl<P, Op, S, L> Plugin<P, Op, S, L> for PrintPlugin
// [...]
{
    // [...]
    fn map(&self, input: Operation<S, L>) -> Operation<Self::Service, Self::Layer> {
        input.layer(PrintLayer { name: Op::NAME })
    }
}

The layer that is registered last via Operation::layer is the one that gets executed first at runtime when a new request comes in, since it wraps the underlying service.

This is why plugins in PluginPipeline are applied in opposite order compared to their registration order: this ensures that, at runtime, their logic is executed in registration order.

source

pub fn http_layer<L>( self, layer: L ) -> PluginPipeline<PluginStack<HttpLayer<L>, P>>

Applies a single [tower::Layer] to all operations before they are deserialized.

Trait Implementations§

source§

impl Default for PluginPipeline<IdentityPlugin>

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<CurrentPlugins> InstrumentExt<CurrentPlugins> for PluginPipeline<CurrentPlugins>

source§

fn instrument( self ) -> PluginPipeline<PluginStack<InstrumentPlugin, CurrentPlugins>>

Applies an InstrumentLayer to all operations which respects the @sensitive trait given on the input and output models. See InstrumentOperation for more information.
source§

impl<P> OperationExtensionExt<P> for PluginPipeline<P>

source§

impl<P, Op, S, L, InnerPlugin> Plugin<P, Op, S, L> for PluginPipeline<InnerPlugin>where InnerPlugin: Plugin<P, Op, S, L>,

§

type Service = <InnerPlugin as Plugin<P, Op, S, L>>::Service

The type of the new Service.
§

type Layer = <InnerPlugin as Plugin<P, Op, S, L>>::Layer

The type of the new Layer.
source§

fn map(&self, input: Operation<S, L>) -> Operation<Self::Service, Self::Layer>

Maps an Operation to another.

Auto Trait Implementations§

§

impl<P> RefUnwindSafe for PluginPipeline<P>where P: RefUnwindSafe,

§

impl<P> Send for PluginPipeline<P>where P: Send,

§

impl<P> Sync for PluginPipeline<P>where P: Sync,

§

impl<P> Unpin for PluginPipeline<P>where P: Unpin,

§

impl<P> UnwindSafe for PluginPipeline<P>where P: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more