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;