1#![deny(clippy::unwrap_used, clippy::dbg_macro, clippy::unimplemented, clippy::todo, clippy::missing_safety_doc)]
6#![warn(
7 clippy::missing_errors_doc,
8 clippy::indexing_slicing,
9 clippy::inline_always,
10 clippy::fn_params_excessive_bools,
11 missing_debug_implementations
12)]
13pub mod backend_service;
15pub mod body;
17pub mod extension;
19pub mod extractor;
21
22pub mod helper_layers;
24pub mod injector;
26pub mod listener;
28pub mod service;
30pub mod utils;
32
33pub use backend_service::ArcHyperService;
34pub use body::SgBody;
35use extension::Reflect;
36pub use extractor::Extract;
37use extractor::OptionalExtract;
38use hyper::{body::Bytes, Request, Response, StatusCode};
39use injector::Inject;
40use std::{convert::Infallible, fmt, ops::Deref};
41pub use tokio_util::sync::CancellationToken;
42pub use tower_layer::Layer;
43use utils::{PathIter, QueryKvIter};
44
45use tower_layer::layer_fn;
46
47pub type BoxResult<T> = Result<T, BoxError>;
48pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
50
51pub type SgRequest = Request<SgBody>;
53pub type SgResponse = Response<SgBody>;
55
56pub trait SgRequestExt {
58 fn with_reflect(&mut self);
59 fn reflect_mut(&mut self) -> &mut Reflect;
60 fn reflect(&self) -> &Reflect;
61 #[cfg(feature = "ext-redis")]
62 fn get_redis_client_by_gateway_name(&self) -> Option<spacegate_ext_redis::RedisClient>;
63 fn extract<M: Extract>(&self) -> M;
64 fn try_extract<M: OptionalExtract>(&self) -> Option<M>;
65 fn inject<I: Inject>(&mut self, i: &I) -> BoxResult<()>;
68 fn defer_call<F>(&mut self, f: F)
69 where
70 F: FnOnce(SgRequest) -> SgRequest + Send + 'static;
71 fn path_iter(&self) -> PathIter;
72 fn query_kv_iter(&self) -> Option<QueryKvIter>;
73}
74
75impl SgRequestExt for SgRequest {
76 fn reflect_mut(&mut self) -> &mut Reflect {
82 self.extensions_mut().get_mut::<Reflect>().expect("reflect extension not found")
83 }
84 fn reflect(&self) -> &Reflect {
90 self.extensions().get::<Reflect>().expect("reflect extension not found")
91 }
92 fn with_reflect(&mut self) {
94 if self.extensions().get::<Reflect>().is_none() {
95 self.extensions_mut().insert(Reflect::new());
96 }
97 }
98
99 #[cfg(feature = "ext-redis")]
100 fn get_redis_client_by_gateway_name(&self) -> Option<spacegate_ext_redis::RedisClient> {
102 self.extensions().get::<extension::GatewayName>().and_then(|gateway_name| spacegate_ext_redis::RedisClientRepo::global().get(gateway_name))
103 }
104
105 fn extract<M: Extract>(&self) -> M {
107 M::extract(self)
108 }
109
110 fn try_extract<M: OptionalExtract>(&self) -> Option<M> {
112 OptionalExtract::extract(self)
113 }
114
115 fn inject<I: Inject>(&mut self, i: &I) -> BoxResult<()> {
117 i.inject(self)
118 }
119
120 fn defer_call<F>(&mut self, f: F)
122 where
123 F: FnOnce(SgRequest) -> SgRequest + Send + 'static,
124 {
125 let defer = self.extensions_mut().get_or_insert_default::<extension::Defer>();
126 defer.push_back(f);
127 }
128
129 fn path_iter(&self) -> PathIter {
130 PathIter::new(self.uri().path())
131 }
132
133 fn query_kv_iter(&self) -> Option<QueryKvIter> {
134 self.uri().query().map(QueryKvIter::new)
135 }
136}
137
138pub trait SgResponseExt {
140 fn with_code_message(code: StatusCode, message: impl Into<Bytes>) -> Self;
141 fn with_code_empty(code: StatusCode) -> Self;
142 fn bad_gateway<E: std::error::Error>(e: E) -> Self
143 where
144 Self: Sized,
145 {
146 let message = e.to_string();
147 let src = e.source();
148 let message = if let Some(src) = src { format!("{}:\n {}", message, src) } else { message };
149 Self::with_code_message(StatusCode::BAD_GATEWAY, message)
150 }
151 fn inherit_reflect(&mut self, req: &SgRequest);
152}
153
154impl SgResponseExt for Response<SgBody> {
155 fn with_code_message(code: StatusCode, message: impl Into<Bytes>) -> Self {
156 let body = SgBody::full(message);
157 let mut resp = Response::builder().status(code).body(body).expect("response builder error");
158 resp.extensions_mut().insert(Reflect::new());
159 resp
160 }
161 fn with_code_empty(code: StatusCode) -> Self {
162 let body = SgBody::empty();
163 let mut resp = Response::builder().status(code).body(body).expect("response builder error");
164 resp.extensions_mut().insert(Reflect::new());
165 resp
166 }
167 fn inherit_reflect(&mut self, req: &SgRequest) {
168 if let Some(reflect) = req.extensions().get::<Reflect>() {
169 self.extensions_mut().extend(reflect.deref().clone());
170 }
171 }
172}
173
174pub struct BoxLayer {
176 boxed: Box<dyn Layer<ArcHyperService, Service = ArcHyperService> + Send + Sync + 'static>,
177}
178
179impl BoxLayer {
180 pub fn new<L>(inner_layer: L) -> Self
182 where
183 L: Layer<ArcHyperService> + Send + Sync + 'static,
184 L::Service: Clone + hyper::service::Service<Request<SgBody>, Response = Response<SgBody>, Error = Infallible> + Send + Sync + 'static,
185 <L::Service as hyper::service::Service<Request<SgBody>>>::Future: Send + 'static,
186 {
187 let layer = layer_fn(move |inner: ArcHyperService| {
188 let out = inner_layer.layer(inner);
189 ArcHyperService::new(out)
190 });
191
192 Self { boxed: Box::new(layer) }
193 }
194
195 #[must_use]
197 pub fn layer_shared(&self, inner: ArcHyperService) -> ArcHyperService {
198 self.boxed.layer(inner)
199 }
200}
201
202impl<S> Layer<S> for BoxLayer
203where
204 S: hyper::service::Service<Request<SgBody>, Response = Response<SgBody>, Error = Infallible> + Send + Sync + 'static,
205 <S as hyper::service::Service<hyper::Request<SgBody>>>::Future: std::marker::Send,
206{
207 type Service = ArcHyperService;
208
209 fn layer(&self, inner: S) -> Self::Service {
210 self.boxed.layer(ArcHyperService::new(inner))
211 }
212}
213
214impl fmt::Debug for BoxLayer {
215 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
216 fmt.debug_struct("BoxLayer").finish()
217 }
218}