1use crate::error::{Error, Result};
4use crate::request::Request;
5use crate::response::Response;
6use async_trait::async_trait;
7use std::sync::Arc;
8
9#[async_trait]
11pub trait Middleware: Send + Sync + 'static {
12 async fn handle(&self, req: Request, next: Next) -> Result<Response>;
13}
14
15#[derive(Clone)]
17pub struct Next {
18 middlewares: Arc<Vec<Arc<dyn Middleware>>>,
19 index: usize,
20}
21
22impl Next {
23 pub fn new(middlewares: Arc<Vec<Arc<dyn Middleware>>>) -> Self {
24 Self {
25 middlewares,
26 index: 0,
27 }
28 }
29
30 pub async fn run(mut self, req: Request) -> Result<Response> {
31 if self.index < self.middlewares.len() {
32 let middleware = self.middlewares[self.index].clone();
33 self.index += 1;
34 middleware.handle(req, self).await
35 } else {
36 Err(Error::not_found("Route not found"))
38 }
39 }
40}
41
42#[async_trait]
45impl<M: Middleware + ?Sized> Middleware for Arc<M> {
46 async fn handle(&self, req: Request, next: Next) -> Result<Response> {
47 (**self).handle(req, next).await
48 }
49}
50
51pub(crate) struct Layered {
53 middlewares: Vec<Arc<dyn Middleware>>,
54 inner: crate::handler::DynHandler,
55}
56
57impl Layered {
58 pub(crate) fn new(
59 middlewares: Vec<Arc<dyn Middleware>>,
60 inner: crate::handler::DynHandler,
61 ) -> Self {
62 Self { middlewares, inner }
63 }
64}
65
66#[async_trait]
67impl crate::handler::Handler for Layered {
68 async fn call(&self, req: Request) -> Result<Response> {
69 let inner = self.inner.clone();
70 let mut chain = self.middlewares.clone();
71 chain.push(Arc::new(move |req: Request, _next: Next| {
72 let inner = inner.clone();
73 async move { inner.call(req).await }
74 }));
75 Next::new(Arc::new(chain)).run(req).await
76 }
77}
78
79#[async_trait]
81impl<F, Fut> Middleware for F
82where
83 F: Fn(Request, Next) -> Fut + Send + Sync + 'static,
84 Fut: std::future::Future<Output = Result<Response>> + Send + 'static,
85{
86 async fn handle(&self, req: Request, next: Next) -> Result<Response> {
87 (self)(req, next).await
88 }
89}
90
91pub async fn logger(req: Request, next: Next) -> Result<Response> {
93 let method = req.method.clone();
94 let uri = req.uri.clone();
95 let start = std::time::Instant::now();
96
97 let response = next.run(req).await;
98
99 let duration = start.elapsed();
100 println!("{} {} - {:?}", method, uri, duration);
101
102 response
103}
104
105#[deprecated(since = "0.4.4", note = "use ullun::cors::Cors")]
110pub fn cors(
111 allowed_origins: Vec<String>,
112) -> impl Fn(
113 Request,
114 Next,
115) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Response>> + Send>>
116 + Clone {
117 let cors = if allowed_origins.iter().any(|o| o == "*") {
118 crate::cors::Cors::new().allow_any_origin()
119 } else {
120 crate::cors::Cors::new()
121 .allow_origins(allowed_origins)
122 .allow_credentials()
123 };
124 let cors = Arc::new(cors);
125 move |req: Request, next: Next| {
126 let cors = cors.clone();
127 Box::pin(async move { cors.handle(req, next).await })
128 }
129}