Module aws_smithy_http_server::operation
source · Expand description
The shape of a Smithy operation is modelled by the OperationShape trait. Its associated types
OperationShape::Input, OperationShape::Output, and OperationShape::Error map to the structures
representing the Smithy inputs, outputs, and errors respectively. When an operation error is not specified
OperationShape::Error is Infallible.
We generate a marker struct for each Smithy operation and implement OperationShape on them. This
is used as a helper - providing static methods and parameterizing other traits.
The model
operation GetShopping {
input: CartIdentifier,
output: ShoppingCart,
errors: [...]
}
is identified with the implementation
pub struct GetShopping;
impl OperationShape for GetShopping {
const NAME: &'static str = "GetShopping";
type Input = CartIdentifier;
type Output = ShoppingCart;
type Error = GetShoppingError;
}The behavior of a Smithy operation is encoded by an Operation. The OperationShape types can be used to
construct specific operations using OperationShapeExt::from_handler and OperationShapeExt::from_service.
The from_handler constructor takes a Handler whereas the
from_service takes a OperationService. Both traits serve a similar purpose -
they provide a common interface over a class of structures.
Handler
The Handler trait is implemented by all async functions which accept OperationShape::Input as their first
argument, the remaining arguments implement FromParts, and return either
OperationShape::Output when OperationShape::Error is Infallible or
Result<OperationShape::Output,OperationShape::Error>. The following are examples of async functions which
implement Handler:
// Simple handler where no error is modelled.
async fn handler_a(input: CartIdentifier) -> ShoppingCart {
todo!()
}
// Handler with an extension where no error is modelled.
async fn handler_b(input: CartIdentifier, ext: Extension<Context>) -> ShoppingCart {
todo!()
}
// More than one extension can be provided.
async fn handler_c(input: CartIdentifier, ext_1: Extension<Context>, ext_2: Extension<ExtraContext>) -> ShoppingCart {
todo!()
}
// When an error is modelled we must return a `Result`.
async fn handler_d(input: CartIdentifier, ext: Extension<Context>) -> Result<ShoppingCart, GetShoppingError> {
todo!()
}OperationService
Similarly, the OperationService trait is implemented by all Service<(Op::Input, ...)> with
Response = Op::Output, and Error = OperationError<Op::Error, PollError>.
We use OperationError, with a PollError not constrained by the model, to allow the user to provide a custom
Service::poll_ready implementation.
The following are examples of Services which implement OperationService:
Service<CartIdentifier, Response = ShoppingCart, Error = OperationError<Infallible, Infallible>>.Service<(CartIdentifier, Extension<Context>), Response = ShoppingCart, Error = OperationError<GetShoppingCartError, Infallible>>.Service<(CartIdentifier, Extension<Context>, Extension<ExtraContext>), Response = ShoppingCart, Error = OperationError<GetShoppingCartError, PollError>).
Notice the parallels between OperationService and Handler.
Constructing an Operation
The following is an example of using both construction approaches:
// Construction of an `Operation` from a `Handler`.
async fn op_handler(input: CartIdentifier) -> Result<ShoppingCart, GetShoppingError> {
todo!()
}
let operation = GetShopping::from_handler(op_handler);
// Construction of an `Operation` from a `Service`.
pub struct PollError;
pub struct OpService;
impl Service<CartIdentifier> for OpService {
type Response = ShoppingCart;
type Error = OperationError<GetShoppingError, PollError>;
type Future = OpFuture;
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
// NOTE: This MUST NOT return `Err(OperationError::Model(_))`.
todo!()
}
fn call(&mut self, request: CartIdentifier) -> Self::Future {
// NOTE: This MUST NOT return `Err(OperationError::Poll(_))`.
todo!()
}
}
let operation = GetShopping::from_service(OpService);
Upgrading Smithy services to HTTP services
Both Handler and OperationService accept and return Smithy model structures. After an Operation is
constructed they are converted to a canonical form
Service<(Op::Input, Exts), Response = Op::Output, Error = OperationError<Op::Error, PollError>>. The
UpgradeLayer acts upon such services by converting them to
Service<http::Request, Response = http::Response, Error = PollError>.
Note that the PollError is still exposed, for two reasons:
- Smithy is agnostic to
PollErrorand therefore we have no prescribed way to serialize it to ahttp::Response, unlike the operation errors. - The intention of
PollErroris to signal that the underlying service is no longer able to take requests, so should be discarded. SeeService::poll_ready.
The UpgradeLayer and it’s Layer::Service Upgrade are both parameterized by a
protocol. This allows for upgrading to Service<http::Request, Response = http::Response, Error = PollError> to be
protocol dependent.
The Operation::upgrade will apply UpgradeLayer to S then apply the Layer L. The
service builder provided to the user will perform this composition on build.
Structs
- A marker struct indicating an
Operationhas not been set in a builder. - A [
Service] provided for everyHandler. - A [
Service] which always returns an internal failure message and logs an error. - A [
Service] normalizing the request type of aOperationService. - A [
Service] responsible for wrapping an operation [Service] accepting and returning Smithy types, and converting it into a [Service] accepting and returninghttptypes. - The [
Service::Future] ofUpgrade. - A [
Layer] responsible for taking an operation [Service], accepting and returning Smithy types and converting it into a [Service] taking and returninghttptypes.
Enums
- The operation
Servicehas two classes of failure modes - those specified by the Smithy model and those associated withService::poll_ready.
Traits
- A utility trait used to provide an even interface for all operation handlers.
- An extension trait for
Handler. - A utility trait used to provide an even interface for all operation services.
- An extension trait of
OperationService. - Models the Smithy Operation shape.
- An extension trait over
OperationShape. - An interface to convert a representation of a Smithy operation into a
Route.