1use tower::{Service, ServiceExt};
4use viz_core::{Body, BoxError, Bytes, Error, Handler, HttpBody, Request, Response, Result};
5
6mod service;
7pub use service::HandlerService;
8
9mod middleware;
10pub use middleware::Middleware;
11
12mod layer;
13pub use layer::Layered;
14
15#[derive(Clone, Debug)]
17pub struct ServiceHandler<S>(S);
18
19impl<S> ServiceHandler<S> {
20 pub const fn new(s: S) -> Self {
22 Self(s)
23 }
24}
25
26#[viz_core::async_trait]
27impl<O, S> Handler<Request> for ServiceHandler<S>
28where
29 O: HttpBody + Send + 'static,
30 O::Data: Into<Bytes>,
31 O::Error: Into<BoxError>,
32 S: Service<Request, Response = Response<O>> + Send + Sync + Clone + 'static,
33 S::Future: Send,
34 S::Error: Into<BoxError>,
35{
36 type Output = Result<Response>;
37
38 async fn call(&self, req: Request) -> Self::Output {
39 self.0
40 .clone()
41 .oneshot(req)
42 .await
43 .map_err(Error::boxed)
44 .map(|resp| resp.map(Body::wrap))
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use std::{
52 sync::{
53 Arc,
54 atomic::{AtomicU64, Ordering},
55 },
56 time::Duration,
57 };
58 use tower::util::{MapErrLayer, MapRequestLayer, MapResponseLayer};
59 use tower::{ServiceBuilder, service_fn};
60 use tower_http::{
61 limit::RequestBodyLimitLayer,
62 request_id::{MakeRequestId, RequestId, SetRequestIdLayer},
63 timeout::TimeoutLayer,
64 };
65 use viz_core::{
66 Body, BoxHandler, Handler, HandlerExt, IntoResponse, Request, RequestExt, Response,
67 };
68
69 #[derive(Clone, Debug, Default)]
70 struct MyMakeRequestId {
71 counter: Arc<AtomicU64>,
72 }
73
74 impl MakeRequestId for MyMakeRequestId {
75 fn make_request_id<B>(&mut self, _: &Request<B>) -> Option<RequestId> {
76 let request_id = self
77 .counter
78 .fetch_add(1, Ordering::SeqCst)
79 .to_string()
80 .parse()
81 .unwrap();
82
83 Some(RequestId::new(request_id))
84 }
85 }
86
87 async fn hello(mut req: Request) -> Result<Response> {
88 let bytes = req.bytes().await?;
89 Ok(bytes.into_response())
90 }
91
92 #[tokio::test]
93 async fn tower_service_into_handler() {
94 let hello_svc = service_fn(hello);
95
96 let svc = ServiceBuilder::new()
97 .layer(RequestBodyLimitLayer::new(1))
98 .layer(MapErrLayer::new(Error::from))
99 .layer(SetRequestIdLayer::x_request_id(MyMakeRequestId::default()))
100 .layer(MapResponseLayer::new(IntoResponse::into_response))
101 .layer(MapRequestLayer::new(|req: Request<_>| req.map(Body::wrap)))
102 .layer(TimeoutLayer::new(Duration::from_secs(10)))
103 .service(hello_svc);
104
105 let r0 = Request::new(Body::Full("12".into()));
106 let h0 = ServiceHandler::new(svc);
107 assert!(h0.call(r0).await.is_err());
108
109 let r1 = Request::new(Body::Full("1".into()));
110 let b0: BoxHandler = h0.boxed();
111 assert!(b0.call(r1).await.is_ok());
112 }
113}