aws_smithy_http_server_python/middleware/
mod.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Schedule pure-Python middlewares as [tower::Layer]s.
7//!
8//! # Moving data from Rust to Python and back
9//!
10//! In middlewares we need to move some data back-and-forth between Rust and Python.
11//! When you move some data from Rust to Python you can't get its ownership back,
12//! you can only get `&T` or `&mut T` but not `T` unless you clone it.
13//!
14//! In order to overcome this shortcoming we are using wrappers for Python that holds
15//! pure-Rust types with [Option]s and provides `take_inner(&mut self) -> Option<T>`
16//! method to get the ownership of `T` back.
17//!
18//! For example:
19//! ```no_run
20//! # use pyo3::prelude::*;
21//! # use pyo3::exceptions::PyRuntimeError;
22//! # enum PyMiddlewareError {
23//! #     InnerGone
24//! # }
25//! # impl From<PyMiddlewareError> for PyErr {
26//! #     fn from(_: PyMiddlewareError) -> PyErr {
27//! #         PyRuntimeError::new_err("inner gone")
28//! #     }
29//! # }
30//! // Pure Rust type
31//! struct Inner {
32//!     num: i32
33//! }
34//!
35//! // Python wrapper
36//! #[pyclass]
37//! pub struct Wrapper(Option<Inner>);
38//!
39//! impl Wrapper {
40//!     // Call when Python is done processing the `Wrapper`
41//!     // to get ownership of `Inner` back
42//!     pub fn take_inner(&mut self) -> Option<Inner> {
43//!         self.0.take()
44//!     }
45//! }
46//!
47//! // Python exposed methods checks if `Wrapper` still has the `Inner` and
48//! // fails with `InnerGone` otherwise.
49//! #[pymethods]
50//! impl Wrapper {
51//!     #[getter]
52//!     fn num(&self) -> PyResult<i32> {
53//!         self.0
54//!             .as_ref()
55//!             .map(|inner| inner.num)
56//!             .ok_or_else(|| PyMiddlewareError::InnerGone.into())
57//!     }
58//!
59//!     #[setter]
60//!     fn set_num(&mut self, num: i32) -> PyResult<()> {
61//!         match self.0.as_mut() {
62//!             Some(inner) => {
63//!                 inner.num = num;
64//!                 Ok(())
65//!             }
66//!             None => Err(PyMiddlewareError::InnerGone.into()),
67//!         }
68//!     }
69//! }
70//! ```
71//!
72//! You can see this pattern in [PyRequest], [PyResponse] and the others.
73//!
74
75mod error;
76mod handler;
77mod header_map;
78mod layer;
79mod request;
80mod response;
81
82pub use self::error::PyMiddlewareError;
83pub use self::handler::PyMiddlewareHandler;
84pub use self::header_map::PyHeaderMap;
85pub use self::layer::PyMiddlewareLayer;
86pub use self::request::PyRequest;
87pub use self::response::PyResponse;