Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and improve middleware related RustDocs. #370

Merged
merged 2 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/net/server/middleware/mandatory.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Core DNS RFC standards based message processing for MUST requirements.
//! RFC 1034, 1035 and other "core" DNS RFC related message processing.
use core::future::{ready, Ready};
use core::marker::PhantomData;
use core::ops::ControlFlow;
Expand Down
19 changes: 13 additions & 6 deletions src/net/server/middleware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@
//!
//! Middleware is implemented in terms of the [`Service`] trait, just like
//! your application service, but also takes a [`Service`] instance as an
//! argument. This is intended to enable middleware to be composed in layers
//! one atop another, each layer receiving and pre-processing requests from
//! the layer beneath, passing them on to the layer above and then
//! post-processing the resulting responses and propagating them back down
//! through the layers to the server.
//! argument.
//!
//! This extra argument enables middleware to be composed in layers one atop
//! another, each layer receiving and pre-processing requests from the layer
//! beneath, passing them on to the layer above and then post-processing the
//! resulting responses and propagating them back down through the layers to
//! the server.
//!
//! A middleware service may also choose to respond immediately to a request
//! without passing it to the layer above. This could be because the
//! middleware determines that the request is invalid, or because the
//! middleware is able to handle and respond to the request entirely on its
//! own.
//!
//! # Middleware layering strategies
//!
Expand All @@ -35,7 +43,6 @@
//! the [`Service`] trait. An example of this can be seen in the
//! [`TsigMiddlewareSvc`][tsig::TsigMiddlewareSvc].
//!
//!
//! Currently the following middleware are available:
//!
//! [`Service`]: crate::net::server::service::Service
Expand Down
78 changes: 74 additions & 4 deletions src/net/server/middleware/stream.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
//! Support for working with response streams needed by all middleware.
//!
//! Like application services all middleware implementations implement the
//! [`Service`] trait and so return a [`futures::stream::Stream`] of
//! responses.
//!
//! A middleware [`Service`] may respond immediately, or pass the request to
//! the next [`Service`] above and then handle the response or responses
//! returned by the upper layer, either passing them through unchanged or
//! post-processing them depending on the purpose of the middleware.
//!
//! Unlike an application service, middleware is not completely in control of
//! the type of response stream that it returns, and may even return a
//! different type in different circumstances. A middleware that passes the
//! responses from the upper service through unchanged must return whatever
//! type of response stream the upper service generates. A middleware that
//! responds immediately returns its own type of response stream. And
//! middleware that post-processes responses received from the upper service
//! may transform the upper service response type to a different response
//! type.
//!
//! The [`MiddlewareStream`] and [`PostprocessingStream`] types provided by
//! this module are intended to simplify and standardize the way that
//! middleware implementations handle these cases.
//!
//! [`futures::stream::Stream`]: futures::stream::Stream
//! [`Service`]: crate::net::server::service::Service
use core::future::Future;
use core::ops::DerefMut;
use core::task::{ready, Context, Poll};
Expand All @@ -13,6 +40,19 @@ use crate::net::server::message::Request;

//------------ MiddlewareStream ----------------------------------------------

/// A [`futures::stream::Stream`] of middleware responses.
///
/// A middleware [`Service`] must be able to respond with different types of
/// response streams depending on the received request or on post-processing
/// applied to responses received from the upper service.
///
/// It is not sufficient therefore to define a single `Service::Stream` type
/// for a middleware [`Service`] impl. Instead middleware should return the
/// [`MiddlewareStream`] enum type which is able to represent the different
/// variants of response stream that may result from middleware processing:
///
/// [`futures::stream::Stream`]: futures::stream::Stream
/// [`Service`]: crate::net::server::service::Service
pub enum MiddlewareStream<
IdentityFuture,
IdentityStream,
Expand All @@ -26,8 +66,7 @@ pub enum MiddlewareStream<
ResultStream: Stream<Item = StreamItem>,
{
/// The inner service response future will be passed through this service
/// without modification, resolving the future first and then the
/// resulting IdentityStream next.
/// without modification, resolving the future into an IdentityStream.
IdentityFuture(IdentityFuture),

/// The inner service response stream will be passed through this service
Expand All @@ -36,10 +75,15 @@ pub enum MiddlewareStream<

/// Either a single response has been created without invoking the inner
/// service, or the inner service response will be post-processed by this
/// service.
/// service. In both cases the response stream is potentially a different
/// type than that of the upper service, i.e. the upper service response
/// stream type is said to be "mapped" to a different response stream
/// type.
Map(MapStream),

/// A response has been created without invoking the inner service.
/// A response has been created without invoking the inner service. Its
/// type may be different to that of the upper service response stream and
/// so is referred to as a "result" stream.
Result(ResultStream),
}

Expand Down Expand Up @@ -115,6 +159,19 @@ type PostprocessingStreamCallback<

//------------ PostprocessingStream ------------------------------------------

/// A [`futures::stream::Stream`] that post-processes responses using a
/// provided callback.
///
/// To post-process an upper service response stream one must first resolve
/// the `Service::Future` into a `Service::Stream` and then apply transforming
/// logic to each of the response stream items as they are received one by one
/// in streaming fashion.
///
/// This type takes care of these details for you so that you can focus on
/// defining the transformation logic via a user supplied callback function
/// which will be invoked on each received response stream item.
///
/// [`futures::stream::Stream`]: futures::stream::Stream
pub struct PostprocessingStream<
RequestOctets,
Future,
Expand Down Expand Up @@ -150,6 +207,19 @@ where
Future: core::future::Future<Output = Stream>,
Stream: futures_util::stream::Stream,
{
/// Creates a new post-processing stream.
///
/// The created post-processing stream will resolve the given
/// `Service::Future` to its `Service::Stream` type and then invoke the
/// given callback on each item in the stream one by one.
///
/// As the original request that resulted in the response stream is often
/// needed in post-processing, e.g. to copy properties of the request to
/// the response, or to vary the behaviour based on the request transport,
/// you must supply the original request when calling this function.
///
/// You may also supply user defined metadata which will be made available
/// to the callback each time it is invoked.
pub fn new(
svc_call_fut: Future,
request: Request<RequestOctets, RequestMeta>,
Expand Down