diff --git a/crates/cache/src/lib.rs b/crates/cache/src/lib.rs index 58a13d354..9a9662661 100644 --- a/crates/cache/src/lib.rs +++ b/crates/cache/src/lib.rs @@ -44,7 +44,11 @@ pub trait CacheIssuer: Send + Sync + 'static { /// The key is used to identify the rate limit. type Key: Hash + Eq + Send + Sync + 'static; /// Issue a new key for the request. If it returns `None`, the request will not be cached. - fn issue(&self, req: &mut Request, depot: &Depot) -> impl Future> + Send; + fn issue( + &self, + req: &mut Request, + depot: &Depot, + ) -> impl Future> + Send; } impl CacheIssuer for F where @@ -153,7 +157,11 @@ pub trait CacheStore: Send + Sync + 'static { Self::Key: Borrow, Q: Hash + Eq + Sync; /// Save the cache item from the store. - fn save_entry(&self, key: Self::Key, data: CachedEntry) -> impl Future> + Send; + fn save_entry( + &self, + key: Self::Key, + data: CachedEntry, + ) -> impl Future> + Send; } /// `CachedBody` is used to save response body to `CachedStore`. @@ -207,7 +215,11 @@ pub struct CachedEntry { impl CachedEntry { /// Create a new `CachedEntry`. pub fn new(status: Option, headers: HeaderMap, body: CachedBody) -> Self { - Self { status, headers, body } + Self { + status, + headers, + body, + } } /// Get the response status. @@ -279,7 +291,13 @@ where S: CacheStore, I: CacheIssuer, { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { if self.skipper.skipped(req, depot) { return; } @@ -309,7 +327,11 @@ where return; } }; - let CachedEntry { status, headers, body } = cache; + let CachedEntry { + status, + headers, + body, + } = cache; if let Some(status) = status { res.status_code(status); } @@ -328,7 +350,10 @@ mod tests { #[handler] async fn cached() -> String { - format!("Hello World, my birth time is {}", OffsetDateTime::now_utc()) + format!( + "Hello World, my birth time is {}", + OffsetDateTime::now_utc() + ) } #[tokio::test] @@ -342,19 +367,25 @@ mod tests { let router = Router::new().hoop(cache).goal(cached); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let content0 = res.take_string().await.unwrap(); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let content1 = res.take_string().await.unwrap(); assert_eq!(content0, content1); tokio::time::sleep(tokio::time::Duration::from_secs(6)).await; - let mut res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; let content2 = res.take_string().await.unwrap(); assert_ne!(content0, content2); diff --git a/crates/compression/src/lib.rs b/crates/compression/src/lib.rs index 0845318c3..b97ca3e64 100644 --- a/crates/compression/src/lib.rs +++ b/crates/compression/src/lib.rs @@ -10,7 +10,9 @@ use std::str::FromStr; use indexmap::IndexMap; use salvo_core::http::body::ResBody; -use salvo_core::http::header::{HeaderValue, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH, CONTENT_TYPE}; +use salvo_core::http::header::{ + HeaderValue, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH, CONTENT_TYPE, +}; use salvo_core::http::{self, mime, Mime, StatusCode}; use salvo_core::{async_trait, Depot, FlowCtrl, Handler, Request, Response}; @@ -264,7 +266,11 @@ impl Compression { self } - fn negotiate(&self, req: &Request, res: &Response) -> Option<(CompressionAlgo, CompressionLevel)> { + fn negotiate( + &self, + req: &Request, + res: &Response, + ) -> Option<(CompressionAlgo, CompressionLevel)> { if req.headers().contains_key(&CONTENT_ENCODING) { return None; } @@ -289,7 +295,10 @@ impl Compression { return None; } } - let header = req.headers().get(ACCEPT_ENCODING).and_then(|v| v.to_str().ok())?; + let header = req + .headers() + .get(ACCEPT_ENCODING) + .and_then(|v| v.to_str().ok())?; let accept_algos = http::parse_accept_encoding(header) .into_iter() @@ -302,7 +311,10 @@ impl Compression { }) .collect::>(); if self.force_priority { - let accept_algos = accept_algos.into_iter().map(|(algo, _)| algo).collect::>(); + let accept_algos = accept_algos + .into_iter() + .map(|(algo, _)| algo) + .collect::>(); self.algos .iter() .find(|(algo, _level)| accept_algos.contains(algo)) @@ -317,7 +329,13 @@ impl Compression { #[async_trait] impl Handler for Compression { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { ctrl.call_next(req, depot, res).await; if ctrl.is_ceased() || res.headers().contains_key(CONTENT_ENCODING) { return; diff --git a/crates/compression/src/stream.rs b/crates/compression/src/stream.rs index 6fa8bab2e..aa73e16ed 100644 --- a/crates/compression/src/stream.rs +++ b/crates/compression/src/stream.rs @@ -37,7 +37,8 @@ impl EncodeStream { impl EncodeStream>> { #[inline] fn poll_chunk(&mut self, cx: &mut Context<'_>) -> Poll>> { - Stream::poll_next(Pin::new(&mut self.body), cx).map_err(|e| IoError::new(ErrorKind::Other, e)) + Stream::poll_next(Pin::new(&mut self.body), cx) + .map_err(|e| IoError::new(ErrorKind::Other, e)) } } impl EncodeStream>> { diff --git a/crates/core/src/catcher.rs b/crates/core/src/catcher.rs index 01d1d74df..6ad79a074 100644 --- a/crates/core/src/catcher.rs +++ b/crates/core/src/catcher.rs @@ -103,7 +103,10 @@ impl Catcher { H: Handler, F: Fn(&Request, &Depot) -> bool + Send + Sync + 'static, { - self.hoops.push(Arc::new(WhenHoop { inner: hoop, filter })); + self.hoops.push(Arc::new(WhenHoop { + inner: hoop, + filter, + })); self } @@ -146,15 +149,29 @@ impl DefaultGoal { } #[async_trait] impl Handler for DefaultGoal { - async fn handle(&self, req: &mut Request, _depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + _depot: &mut Depot, + res: &mut Response, + _ctrl: &mut FlowCtrl, + ) { let status = res.status_code.unwrap_or(StatusCode::NOT_FOUND); - if (status.is_server_error() || status.is_client_error()) && (res.body.is_none() || res.body.is_error()) { + if (status.is_server_error() || status.is_client_error()) + && (res.body.is_none() || res.body.is_error()) + { write_error_default(req, res, self.footer.as_deref()); } } } -fn status_error_html(code: StatusCode, name: &str, brief: &str, cause: Option<&str>, footer: Option<&str>) -> String { +fn status_error_html( + code: StatusCode, + name: &str, + brief: &str, + cause: Option<&str>, + footer: Option<&str>, +) -> String { format!( r#" @@ -253,7 +270,11 @@ fn status_error_xml(code: StatusCode, name: &str, brief: &str, cause: Option<&st /// Create bytes from `StatusError`. #[doc(hidden)] #[inline] -pub fn status_error_bytes(err: &StatusError, prefer_format: &Mime, footer: Option<&str>) -> (Mime, Bytes) { +pub fn status_error_bytes( + err: &StatusError, + prefer_format: &Mime, + footer: Option<&str>, +) -> (Mime, Bytes) { let format = if !SUPPORTED_FORMATS.contains(&prefer_format.subtype()) { mime::TEXT_HTML } else { @@ -309,7 +330,13 @@ mod tests { } #[handler] - async fn handle404(&self, _req: &Request, _depot: &Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle404( + &self, + _req: &Request, + _depot: &Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { if res.status_code.is_none() || Some(StatusCode::NOT_FOUND) == res.status_code { res.render("Custom 404 Error Page"); ctrl.skip_rest(); diff --git a/crates/core/src/conn/joined.rs b/crates/core/src/conn/joined.rs index e6c4a3d23..c8ddf0c20 100644 --- a/crates/core/src/conn/joined.rs +++ b/crates/core/src/conn/joined.rs @@ -29,7 +29,11 @@ where B: AsyncRead + Send + Unpin + 'static, { #[inline] - fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { match &mut self.get_mut() { JoinedStream::A(a) => Pin::new(a).poll_read(cx, buf), JoinedStream::B(b) => Pin::new(b).poll_read(cx, buf), @@ -95,7 +99,12 @@ where async fn try_bind(self) -> crate::Result { let a = self.a.try_bind().await?; let b = self.b.try_bind().await?; - let holdings = a.holdings().iter().chain(b.holdings().iter()).cloned().collect(); + let holdings = a + .holdings() + .iter() + .chain(b.holdings().iter()) + .cloned() + .collect(); Ok(JoinedAcceptor { a, b, holdings }) } } @@ -148,7 +157,10 @@ where } #[inline] - async fn accept(&mut self, fuse_factory: Option) -> IoResult> { + async fn accept( + &mut self, + fuse_factory: Option, + ) -> IoResult> { tokio::select! { accepted = self.a.accept(fuse_factory.clone()) => { Ok(accepted?.map_conn(JoinedStream::A)) @@ -173,7 +185,10 @@ mod tests { let addr1 = std::net::SocketAddr::from(([127, 0, 0, 1], 6978)); let addr2 = std::net::SocketAddr::from(([127, 0, 0, 1], 6979)); - let mut acceptor = TcpListener::new(addr1).join(TcpListener::new(addr2)).bind().await; + let mut acceptor = TcpListener::new(addr1) + .join(TcpListener::new(addr2)) + .bind() + .await; tokio::spawn(async move { let mut stream = TcpStream::connect(addr1).await.unwrap(); stream.write_i32(50).await.unwrap(); diff --git a/crates/core/src/conn/proto.rs b/crates/core/src/conn/proto.rs index 94a668f97..3a62cd663 100644 --- a/crates/core/src/conn/proto.rs +++ b/crates/core/src/conn/proto.rs @@ -102,7 +102,11 @@ impl HttpBuilder { match version { Version::HTTP_10 | Version::HTTP_11 => { #[cfg(not(feature = "http1"))] - return Err(std::io::Error::new(std::io::ErrorKind::Other, "http1 feature not enabled").into()); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "http1 feature not enabled", + ) + .into()); #[cfg(feature = "http1")] { let mut conn = self @@ -163,7 +167,11 @@ impl HttpBuilder { } Version::HTTP_2 => { #[cfg(not(feature = "http2"))] - return Err(std::io::Error::new(std::io::ErrorKind::Other, "http2 feature not enabled").into()); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "http2 feature not enabled", + ) + .into()); #[cfg(feature = "http2")] { let mut conn = self.http2.serve_connection(TokioIo::new(socket), service); @@ -305,7 +313,11 @@ impl AsyncRead for Rewind where T: AsyncRead + Unpin, { - fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { if let Some(mut prefix) = self.pre.take() { // If there are no remaining bytes, let the bytes get dropped. if !prefix.is_empty() { @@ -328,7 +340,11 @@ impl AsyncWrite for Rewind where T: AsyncWrite + Unpin, { - fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &[u8], + ) -> Poll> { Pin::new(&mut self.inner).poll_write(cx, buf) } diff --git a/crates/core/src/conn/stream/straight.rs b/crates/core/src/conn/stream/straight.rs index 2972d55fd..8f0bda479 100644 --- a/crates/core/src/conn/stream/straight.rs +++ b/crates/core/src/conn/stream/straight.rs @@ -59,7 +59,11 @@ impl AsyncRead for StraightStream where C: AsyncRead, { - fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { let this = self.project(); let remaining = buf.remaining(); match this.inner.poll_read(cx, buf) { @@ -119,7 +123,11 @@ where this.inner.poll_shutdown(cx) } - fn poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) -> Poll> { + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { let this = self.project(); if let Some(fusewire) = &this.fusewire { fusewire.event(FuseEvent::Alive); diff --git a/crates/core/src/conn/tcp.rs b/crates/core/src/conn/tcp.rs index 87f9af2b9..31d9b6572 100644 --- a/crates/core/src/conn/tcp.rs +++ b/crates/core/src/conn/tcp.rs @@ -40,7 +40,10 @@ impl TcpListener { #[inline] pub fn new(local_addr: T) -> Self { #[cfg(not(feature = "socket2"))] - TcpListener { local_addr, ttl: None } + TcpListener { + local_addr, + ttl: None, + } } /// Bind to socket address. #[cfg(feature = "socket2")] @@ -207,7 +210,10 @@ impl Acceptor for TcpAcceptor { } #[inline] - async fn accept(&mut self, fuse_factory: Option) -> IoResult> { + async fn accept( + &mut self, + fuse_factory: Option, + ) -> IoResult> { self.inner.accept().await.map(move |(conn, remote_addr)| { let local_addr = self.holdings[0].local_addr.clone(); Accepted { @@ -239,7 +245,11 @@ mod tests { async fn test_tcp_listener() { let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 6878)); let mut acceptor = TcpListener::new(addr).bind().await; - let addr = acceptor.holdings()[0].local_addr.clone().into_std().unwrap(); + let addr = acceptor.holdings()[0] + .local_addr + .clone() + .into_std() + .unwrap(); tokio::spawn(async move { let mut stream = TcpStream::connect(addr).await.unwrap(); stream.write_i32(150).await.unwrap(); diff --git a/crates/core/src/depot.rs b/crates/core/src/depot.rs index 1e27ec61e..ef29de5ca 100644 --- a/crates/core/src/depot.rs +++ b/crates/core/src/depot.rs @@ -47,7 +47,9 @@ impl Depot { /// The depot is initially created with a capacity of 0, so it will not allocate until it is first inserted into. #[inline] pub fn new() -> Depot { - Depot { map: HashMap::new() } + Depot { + map: HashMap::new(), + } } /// Get reference to depot inner map. @@ -92,7 +94,9 @@ impl Depot { /// Returns `Err(None)` if value is not present in depot. /// Returns `Err(Some(Box))` if value is present in depot but downcast failed. #[inline] - pub fn obtain_mut(&mut self) -> Result<&mut T, Option<&mut Box>> { + pub fn obtain_mut( + &mut self, + ) -> Result<&mut T, Option<&mut Box>> { self.get_mut(&type_key::()) } @@ -125,7 +129,10 @@ impl Depot { /// Returns `Err(None)` if value is not present in depot. /// Returns `Err(Some(Box))` if value is present in depot but downcast failed. #[inline] - pub fn get(&self, key: &str) -> Result<&V, Option<&Box>> { + pub fn get( + &self, + key: &str, + ) -> Result<&V, Option<&Box>> { if let Some(value) = self.map.get(key) { value.downcast_ref::().ok_or(Some(value)) } else { @@ -143,7 +150,9 @@ impl Depot { ) -> Result<&mut V, Option<&mut Box>> { if let Some(value) = self.map.get_mut(key) { if value.downcast_mut::().is_some() { - Ok(value.downcast_mut::().expect("downcast_mut shuold not be failed")) + Ok(value + .downcast_mut::() + .expect("downcast_mut shuold not be failed")) } else { Err(Some(value)) } @@ -154,7 +163,10 @@ impl Depot { /// Remove value from depot and returning the value at the key if the key was previously in the depot. #[inline] - pub fn remove(&mut self, key: &str) -> Result>> { + pub fn remove( + &mut self, + key: &str, + ) -> Result>> { if let Some(value) = self.map.remove(key) { value.downcast::().map(|b| *b).map_err(Some) } else { @@ -170,14 +182,18 @@ impl Depot { /// Remove value from depot and returning the value if the type was previously in the depot. #[inline] - pub fn scrape(&mut self) -> Result>> { + pub fn scrape( + &mut self, + ) -> Result>> { self.remove(&type_key::()) } } impl fmt::Debug for Depot { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Depot").field("keys", &self.map.keys()).finish() + f.debug_struct("Depot") + .field("keys", &self.map.keys()) + .finish() } } @@ -197,19 +213,30 @@ mod test { assert!(depot.contains_key("one")); assert_eq!(depot.get::("one").unwrap(), &"ONE".to_owned()); - assert_eq!(depot.get_mut::("one").unwrap(), &mut "ONE".to_owned()); + assert_eq!( + depot.get_mut::("one").unwrap(), + &mut "ONE".to_owned() + ); } #[tokio::test] async fn test_middleware_use_depot() { #[handler] - async fn set_user(req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn set_user( + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { depot.insert("user", "client"); ctrl.call_next(req, depot, res).await; } #[handler] async fn hello(depot: &mut Depot) -> String { - format!("Hello {}", depot.get::<&str>("user").copied().unwrap_or_default()) + format!( + "Hello {}", + depot.get::<&str>("user").copied().unwrap_or_default() + ) } let router = Router::new().hoop(set_user).goal(hello); let service = Service::new(router); diff --git a/crates/core/src/extract/case.rs b/crates/core/src/extract/case.rs index f961240b0..ab3fb8af2 100644 --- a/crates/core/src/extract/case.rs +++ b/crates/core/src/extract/case.rs @@ -68,7 +68,9 @@ impl RenameRule { } ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(), KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"), - ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-"), + ScreamingKebabCase => ScreamingSnakeCase + .apply_to_variant(variant) + .replace('_', "-"), } } @@ -111,7 +113,8 @@ mod tests { fn test_rename_variants() { for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[ ( - "Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME", + "Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", + "OUTCOME", ), ( "VeryTasty", @@ -133,7 +136,10 @@ mod tests { assert_eq!(SnakeCase.apply_to_variant(original), snake); assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming); assert_eq!(KebabCase.apply_to_variant(original), kebab); - assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab); + assert_eq!( + ScreamingKebabCase.apply_to_variant(original), + screaming_kebab + ); } } diff --git a/crates/core/src/extract/metadata.rs b/crates/core/src/extract/metadata.rs index 9d66383d6..eeac85786 100644 --- a/crates/core/src/extract/metadata.rs +++ b/crates/core/src/extract/metadata.rs @@ -31,7 +31,9 @@ impl FromStr for SourceFrom { #[cfg(feature = "cookie")] "cookie" => Ok(Self::Cookie), "body" => Ok(Self::Body), - _ => Err(crate::Error::Other(format!("invalid source from `{input}`").into())), + _ => Err(crate::Error::Other( + format!("invalid source from `{input}`").into(), + )), } } } @@ -130,7 +132,11 @@ impl Metadata { /// Check is this type has body required. pub(crate) fn has_body_required(&self) -> bool { - if self.default_sources.iter().any(|s| s.from == SourceFrom::Body) { + if self + .default_sources + .iter() + .any(|s| s.from == SourceFrom::Body) + { return true; } self.fields.iter().any(|f| f.has_body_required()) @@ -260,7 +266,10 @@ mod tests { #[test] fn test_parse_source_format() { - for (key, value) in [("multimap", SourceParser::MultiMap), ("json", SourceParser::Json)] { + for (key, value) in [ + ("multimap", SourceParser::MultiMap), + ("json", SourceParser::Json), + ] { assert_eq!(key.parse::().unwrap(), value); } assert!("abcd".parse::().is_err()); diff --git a/crates/core/src/fs/mod.rs b/crates/core/src/fs/mod.rs index 604588e08..27d16ec6a 100644 --- a/crates/core/src/fs/mod.rs +++ b/crates/core/src/fs/mod.rs @@ -41,8 +41,13 @@ where match self.state { ChunkedState::File(ref mut file) => { - let mut file = file.take().expect("`ChunkedReadFile` polled after completion"); - let max_bytes = cmp::min(self.total_size.saturating_sub(self.read_size), self.buffer_size) as usize; + let mut file = file + .take() + .expect("`ChunkedReadFile` polled after completion"); + let max_bytes = cmp::min( + self.total_size.saturating_sub(self.read_size), + self.buffer_size, + ) as usize; let offset = self.offset; let fut = tokio::task::spawn_blocking(move || { let mut buf = Vec::with_capacity(max_bytes); @@ -58,8 +63,8 @@ where self.poll_next(cx) } ChunkedState::Future(ref mut fut) => { - let (file, bytes) = - ready!(Pin::new(fut).poll(cx)).map_err(|_| IoError::new(ErrorKind::Other, "BlockingErr"))??; + let (file, bytes) = ready!(Pin::new(fut).poll(cx)) + .map_err(|_| IoError::new(ErrorKind::Other, "BlockingErr"))??; self.state = ChunkedState::File(Some(file)); self.offset += bytes.len() as u64; @@ -121,7 +126,9 @@ mod test { assert_eq!(file.content_type(), &Mime::from_str("text/html").unwrap()); assert_eq!( file.content_disposition(), - Some(&HeaderValue::from_static("attachment; filename=attach.file")) + Some(&HeaderValue::from_static( + "attachment; filename=attach.file" + )) ); } } diff --git a/crates/core/src/fs/named_file.rs b/crates/core/src/fs/named_file.rs index 189012819..540710c21 100644 --- a/crates/core/src/fs/named_file.rs +++ b/crates/core/src/fs/named_file.rs @@ -170,7 +170,9 @@ impl NamedFileBuilder { && ct.get_param(mime::CHARSET).is_none() { //TODO: auto detect charset - format!("{ct}; charset=utf-8").parse::().unwrap_or(ct) + format!("{ct}; charset=utf-8") + .parse::() + .unwrap_or(ct) } else { ct } @@ -178,7 +180,11 @@ impl NamedFileBuilder { let metadata = file.metadata().await?; let modified = metadata.modified().ok(); let content_encoding = match content_encoding { - Some(content_encoding) => Some(content_encoding.parse::().map_err(Error::other)?), + Some(content_encoding) => Some( + content_encoding + .parse::() + .map_err(Error::other)?, + ), None => None, }; @@ -215,9 +221,8 @@ fn build_content_disposition( "attachment" } else { match (content_type.type_(), content_type.subtype()) { - (mime::IMAGE | mime::TEXT | mime::VIDEO | mime::AUDIO, _) | (_, mime::JAVASCRIPT | mime::JSON) => { - "inline" - } + (mime::IMAGE | mime::TEXT | mime::VIDEO | mime::AUDIO, _) + | (_, mime::JAVASCRIPT | mime::JSON) => "inline", _ => "attachment", } } @@ -236,7 +241,9 @@ fn build_content_disposition( .parse::() .map_err(Error::other)? } else { - disposition_type.parse::().map_err(Error::other)? + disposition_type + .parse::() + .map_err(Error::other)? }; Ok(content_disposition) } @@ -427,7 +434,8 @@ impl NamedFile { true } else if req_headers.contains_key(IF_NONE_MATCH) { false - } else if let (Some(last_modified), Some(since)) = (&last_modified, req_headers.typed_get::()) + } else if let (Some(last_modified), Some(since)) = + (&last_modified, req_headers.typed_get::()) { !since.is_modified(*last_modified) } else { @@ -436,12 +444,14 @@ impl NamedFile { if self.flags.contains(Flag::ContentDisposition) { if let Some(content_disposition) = self.content_disposition.take() { - res.headers_mut().insert(CONTENT_DISPOSITION, content_disposition); + res.headers_mut() + .insert(CONTENT_DISPOSITION, content_disposition); } else if !res.headers().contains_key(CONTENT_DISPOSITION) { // skip to set CONTENT_DISPOSITION header if it is already set. match build_content_disposition(&self.path, &self.content_type, None, None) { Ok(content_disposition) => { - res.headers_mut().insert(CONTENT_DISPOSITION, content_disposition); + res.headers_mut() + .insert(CONTENT_DISPOSITION, content_disposition); } Err(e) => { tracing::error!(error = ?e, "build file's content disposition failed"); @@ -462,7 +472,8 @@ impl NamedFile { let mut length = self.metadata.len(); if let Some(content_encoding) = &self.content_encoding { - res.headers_mut().insert(CONTENT_ENCODING, content_encoding.clone()); + res.headers_mut() + .insert(CONTENT_ENCODING, content_encoding.clone()); } let mut offset = 0; @@ -474,7 +485,8 @@ impl NamedFile { length = range[0].length; offset = range[0].start; } else { - res.headers_mut().typed_insert(ContentRange::unsatisfied_bytes(length)); + res.headers_mut() + .typed_insert(ContentRange::unsatisfied_bytes(length)); res.status_code(StatusCode::RANGE_NOT_SATISFIABLE); return; }; @@ -509,7 +521,8 @@ impl NamedFile { state: ChunkedState::File(Some(self.file.into_std().await)), buffer_size: self.buffer_size, }; - res.headers_mut().typed_insert(ContentLength(reader.total_size)); + res.headers_mut() + .typed_insert(ContentLength(reader.total_size)); res.stream(reader); } else { res.status_code(StatusCode::OK); diff --git a/crates/core/src/fuse/flex.rs b/crates/core/src/fuse/flex.rs index b4a73aade..2570da4eb 100644 --- a/crates/core/src/fuse/flex.rs +++ b/crates/core/src/fuse/flex.rs @@ -106,9 +106,12 @@ impl Fusewire for FlexFusewire { let tls_handshake_token = self.tls_handshake_token.clone(); tokio::spawn(async move { loop { - if tokio::time::timeout(tls_handshake_timeout, tls_handshake_notify.notified()) - .await - .is_err() + if tokio::time::timeout( + tls_handshake_timeout, + tls_handshake_notify.notified(), + ) + .await + .is_err() { tls_handshake_token.cancel(); break; diff --git a/crates/core/src/handler.rs b/crates/core/src/handler.rs index 6f9b47d58..e6e65a6ee 100644 --- a/crates/core/src/handler.rs +++ b/crates/core/src/handler.rs @@ -137,7 +137,13 @@ pub trait Handler: Send + Sync + 'static { } /// Handle http request. #[must_use = "handle future must be used"] - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl); + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ); /// Wrap to `HoopedHandler`. #[inline] @@ -175,7 +181,13 @@ pub trait Handler: Send + Sync + 'static { pub struct EmptyHandler; #[async_trait] impl Handler for EmptyHandler { - async fn handle(&self, _req: &mut Request, _depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) { + async fn handle( + &self, + _req: &mut Request, + _depot: &mut Depot, + res: &mut Response, + _ctrl: &mut FlowCtrl, + ) { res.status_code(StatusCode::OK); } } @@ -204,7 +216,13 @@ where H: Handler, F: Fn(&Request, &Depot) -> bool + Send + Sync + 'static, { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { if (self.filter)(req, depot) { self.inner.handle(req, depot, res, ctrl).await; } @@ -275,7 +293,13 @@ impl HoopedHandler { } #[async_trait] impl Handler for HoopedHandler { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + _ctrl: &mut FlowCtrl, + ) { let inner: Arc = self.inner.clone(); let mut ctrl = FlowCtrl::new(self.hoops.iter().chain([&inner]).cloned().collect()); ctrl.call_next(req, depot, res).await; diff --git a/crates/core/src/http/body/channel.rs b/crates/core/src/http/body/channel.rs index 4bca62e72..c3f9c542b 100644 --- a/crates/core/src/http/body/channel.rs +++ b/crates/core/src/http/body/channel.rs @@ -79,17 +79,18 @@ impl BodySender { } impl futures_util::AsyncWrite for BodySender { - fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { match self.data_tx.poll_ready(cx) { Poll::Ready(Ok(())) => { let data: Bytes = Bytes::from(buf.to_vec()); let len = buf.len(); - Poll::Ready( - self.data_tx - .try_send(Ok(data)) - .map(|_| len) - .map_err(|e| IoError::new(ErrorKind::Other, format!("failed to send data: {}", e))), - ) + Poll::Ready(self.data_tx.try_send(Ok(data)).map(|_| len).map_err(|e| { + IoError::new(ErrorKind::Other, format!("failed to send data: {}", e)) + })) } Poll::Ready(Err(e)) => Poll::Ready(Err(IoError::new( ErrorKind::Other, @@ -113,17 +114,18 @@ impl futures_util::AsyncWrite for BodySender { } impl tokio::io::AsyncWrite for BodySender { - fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { match self.data_tx.poll_ready(cx) { Poll::Ready(Ok(())) => { let data: Bytes = Bytes::from(buf.to_vec()); let len = buf.len(); - Poll::Ready( - self.data_tx - .try_send(Ok(data)) - .map(|_| len) - .map_err(|e| IoError::new(ErrorKind::Other, format!("failed to send data: {}", e))), - ) + Poll::Ready(self.data_tx.try_send(Ok(data)).map(|_| len).map_err(|e| { + IoError::new(ErrorKind::Other, format!("failed to send data: {}", e)) + })) } Poll::Ready(Err(e)) => Poll::Ready(Err(IoError::new( ErrorKind::Other, diff --git a/crates/core/src/http/body/req.rs b/crates/core/src/http/body/req.rs index 4f795b7d6..ac8aaf092 100644 --- a/crates/core/src/http/body/req.rs +++ b/crates/core/src/http/body/req.rs @@ -11,7 +11,8 @@ use bytes::Bytes; use crate::fuse::{ArcFusewire, FuseEvent}; use crate::BoxedError; -pub(crate) type BoxedBody = Pin + Send + Sync + 'static>>; +pub(crate) type BoxedBody = + Pin + Send + Sync + 'static>>; pub(crate) type PollFrame = Poll, IoError>>>; /// Body for HTTP request. @@ -167,7 +168,10 @@ impl From for ReqBody { } impl From for ReqBody { fn from(inner: Incoming) -> Self { - Self::Hyper { inner, fusewire: None } + Self::Hyper { + inner, + fusewire: None, + } } } impl From for ReqBody { @@ -180,10 +184,16 @@ impl TryFrom for Incoming { type Error = crate::Error; fn try_from(body: ReqBody) -> Result { match body { - ReqBody::None => Err(crate::Error::other("ReqBody::None cannot convert to Incoming")), - ReqBody::Once(_) => Err(crate::Error::other("ReqBody::Bytes cannot convert to Incoming")), + ReqBody::None => Err(crate::Error::other( + "ReqBody::None cannot convert to Incoming", + )), + ReqBody::Once(_) => Err(crate::Error::other( + "ReqBody::Bytes cannot convert to Incoming", + )), ReqBody::Hyper { inner, .. } => Ok(inner), - ReqBody::Boxed { .. } => Err(crate::Error::other("ReqBody::Boxed cannot convert to Incoming")), + ReqBody::Boxed { .. } => Err(crate::Error::other( + "ReqBody::Boxed cannot convert to Incoming", + )), } } } @@ -293,7 +303,10 @@ impl fmt::Debug for ReqBody { match self { ReqBody::None => write!(f, "ReqBody::None"), ReqBody::Once(value) => f.debug_tuple("ReqBody::Once").field(value).finish(), - ReqBody::Hyper { inner, .. } => f.debug_struct("ReqBody::Hyper").field("inner", inner).finish(), + ReqBody::Hyper { inner, .. } => f + .debug_struct("ReqBody::Hyper") + .field("inner", inner) + .finish(), ReqBody::Boxed { .. } => write!(f, "ReqBody::Boxed{{..}}"), } } diff --git a/crates/core/src/http/body/res.rs b/crates/core/src/http/body/res.rs index 103c17905..cef706b5b 100644 --- a/crates/core/src/http/body/res.rs +++ b/crates/core/src/http/body/res.rs @@ -102,7 +102,10 @@ impl ResBody { data_tx, trailers_tx: Some(trailers_tx), }; - let rx = ResBody::Channel(BodyReceiver { data_rx, trailers_rx }); + let rx = ResBody::Channel(BodyReceiver { + data_rx, + trailers_rx, + }); (tx, rx) } @@ -147,16 +150,22 @@ impl Body for ResBody { Poll::Ready(Some(Ok(Frame::data(bytes)))) } } - Self::Chunks(chunks) => Poll::Ready(chunks.pop_front().map(|bytes| Ok(Frame::data(bytes)))), + Self::Chunks(chunks) => { + Poll::Ready(chunks.pop_front().map(|bytes| Ok(Frame::data(bytes)))) + } Self::Hyper(body) => match Body::poll_frame(Pin::new(body), cx) { Poll::Ready(Some(Ok(frame))) => Poll::Ready(Some(Ok(frame))), - Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(IoError::new(ErrorKind::Other, e)))), + Poll::Ready(Some(Err(e))) => { + Poll::Ready(Some(Err(IoError::new(ErrorKind::Other, e)))) + } Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending, }, Self::Boxed(body) => match Body::poll_frame(Pin::new(body), cx) { Poll::Ready(Some(Ok(frame))) => Poll::Ready(Some(Ok(frame))), - Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(IoError::new(ErrorKind::Other, e)))), + Poll::Ready(Some(Err(e))) => { + Poll::Ready(Some(Err(IoError::new(ErrorKind::Other, e)))) + } Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending, }, diff --git a/crates/core/src/http/errors/parse_error.rs b/crates/core/src/http/errors/parse_error.rs index 40ef6e36d..cd8c8dddb 100644 --- a/crates/core/src/http/errors/parse_error.rs +++ b/crates/core/src/http/errors/parse_error.rs @@ -104,7 +104,11 @@ impl ParseError { #[async_trait] impl Writer for ParseError { async fn write(self, _req: &mut Request, _depot: &mut Depot, res: &mut Response) { - res.render(StatusError::bad_request().brief("parse http data failed.").cause(self)); + res.render( + StatusError::bad_request() + .brief("parse http data failed.") + .cause(self), + ); } } diff --git a/crates/core/src/http/errors/status_error.rs b/crates/core/src/http/errors/status_error.rs index f0b58f90d..973e9eca8 100644 --- a/crates/core/src/http/errors/status_error.rs +++ b/crates/core/src/http/errors/status_error.rs @@ -192,7 +192,10 @@ impl StdError for StatusError {} impl Display for StatusError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let mut str_error = format!("code: {} name: {} brief: {}", self.code, self.name, self.brief); + let mut str_error = format!( + "code: {} name: {} brief: {}", + self.code, self.name, self.brief + ); if let Some(detail) = &self.detail { write!(&mut str_error, " detail: {}", detail)?; } @@ -214,7 +217,9 @@ impl StatusError { StatusCode::NOT_FOUND => Some(StatusError::not_found()), StatusCode::METHOD_NOT_ALLOWED => Some(StatusError::method_not_allowed()), StatusCode::NOT_ACCEPTABLE => Some(StatusError::not_acceptable()), - StatusCode::PROXY_AUTHENTICATION_REQUIRED => Some(StatusError::proxy_authentication_required()), + StatusCode::PROXY_AUTHENTICATION_REQUIRED => { + Some(StatusError::proxy_authentication_required()) + } StatusCode::REQUEST_TIMEOUT => Some(StatusError::request_timeout()), StatusCode::CONFLICT => Some(StatusError::conflict()), StatusCode::GONE => Some(StatusError::gone()), @@ -233,19 +238,27 @@ impl StatusError { StatusCode::UPGRADE_REQUIRED => Some(StatusError::upgrade_required()), StatusCode::PRECONDITION_REQUIRED => Some(StatusError::precondition_required()), StatusCode::TOO_MANY_REQUESTS => Some(StatusError::too_many_requests()), - StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE => Some(StatusError::request_header_fields_toolarge()), - StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS => Some(StatusError::unavailable_for_legalreasons()), + StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE => { + Some(StatusError::request_header_fields_toolarge()) + } + StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS => { + Some(StatusError::unavailable_for_legalreasons()) + } StatusCode::INTERNAL_SERVER_ERROR => Some(StatusError::internal_server_error()), StatusCode::NOT_IMPLEMENTED => Some(StatusError::not_implemented()), StatusCode::BAD_GATEWAY => Some(StatusError::bad_gateway()), StatusCode::SERVICE_UNAVAILABLE => Some(StatusError::service_unavailable()), StatusCode::GATEWAY_TIMEOUT => Some(StatusError::gateway_timeout()), - StatusCode::HTTP_VERSION_NOT_SUPPORTED => Some(StatusError::http_version_not_supported()), + StatusCode::HTTP_VERSION_NOT_SUPPORTED => { + Some(StatusError::http_version_not_supported()) + } StatusCode::VARIANT_ALSO_NEGOTIATES => Some(StatusError::variant_also_negotiates()), StatusCode::INSUFFICIENT_STORAGE => Some(StatusError::insufficient_storage()), StatusCode::LOOP_DETECTED => Some(StatusError::loop_detected()), StatusCode::NOT_EXTENDED => Some(StatusError::not_extended()), - StatusCode::NETWORK_AUTHENTICATION_REQUIRED => Some(StatusError::network_authentication_required()), + StatusCode::NETWORK_AUTHENTICATION_REQUIRED => { + Some(StatusError::network_authentication_required()) + } _ => None, } } diff --git a/crates/core/src/http/form.rs b/crates/core/src/http/form.rs index c8917413a..7921d9f97 100644 --- a/crates/core/src/http/form.rs +++ b/crates/core/src/http/form.rs @@ -50,7 +50,10 @@ impl FormData { .and_then(|v| v.parse().ok()); match ctype { Some(ctype) if ctype.subtype() == mime::WWW_FORM_URLENCODED => { - let data = BodyExt::collect(body).await.map_err(ParseError::other)?.to_bytes(); + let data = BodyExt::collect(body) + .await + .map_err(ParseError::other)? + .to_bytes(); let mut form_data = FormData::new(); form_data.fields = form_urlencoded::parse(&data).into_owned().collect(); Ok(form_data) @@ -67,7 +70,9 @@ impl FormData { while let Some(mut field) = multipart.next_field().await? { if let Some(name) = field.name().map(|s| s.to_owned()) { if field.headers().get(CONTENT_TYPE).is_some() { - form_data.files.insert(name, FilePart::create(&mut field).await?); + form_data + .files + .insert(name, FilePart::create(&mut field).await?); } else { form_data.fields.insert(name, field.text().await?); } @@ -150,10 +155,11 @@ impl FilePart { /// deleted once the FilePart object goes out of scope). pub async fn create(field: &mut Field<'_>) -> Result { // Setup a file to capture the contents. - let mut path = tokio::task::spawn_blocking(|| Builder::new().prefix("salvo_http_multipart").tempdir()) - .await - .expect("Runtime spawn blocking poll error")? - .into_path(); + let mut path = + tokio::task::spawn_blocking(|| Builder::new().prefix("salvo_http_multipart").tempdir()) + .await + .expect("Runtime spawn blocking poll error")? + .into_path(); let temp_dir = Some(path.clone()); let name = field.file_name().map(|s| s.to_owned()); path.push(format!( diff --git a/crates/core/src/http/mod.rs b/crates/core/src/http/mod.rs index 62594f20a..19b6a6336 100644 --- a/crates/core/src/http/mod.rs +++ b/crates/core/src/http/mod.rs @@ -87,7 +87,12 @@ pub fn parse_accept_encoding(header: &str) -> Vec<(String, u8)> { pub fn guess_accept_mime(req: &Request, default_type: Option) -> Mime { let dmime: Mime = default_type.unwrap_or(mime::TEXT_HTML); let accept = req.accept(); - accept.first().unwrap_or(&dmime).to_string().parse().unwrap_or(dmime) + accept + .first() + .unwrap_or(&dmime) + .to_string() + .parse() + .unwrap_or(dmime) } #[cfg(test)] diff --git a/crates/core/src/http/range.rs b/crates/core/src/http/range.rs index ea50628e4..49f3bcee5 100644 --- a/crates/core/src/http/range.rs +++ b/crates/core/src/http/range.rs @@ -128,33 +128,116 @@ mod tests { T("bytes=0x01-0x02", 10, vec![]), T("bytes= ", 10, vec![]), T("bytes= , , , ", 10, vec![]), - T("bytes=0-9", 10, vec![HttpRange { start: 0, length: 10 }]), - T("bytes=0-", 10, vec![HttpRange { start: 0, length: 10 }]), - T("bytes=5-", 10, vec![HttpRange { start: 5, length: 5 }]), - T("bytes=0-20", 10, vec![HttpRange { start: 0, length: 10 }]), - T("bytes=15-,0-5", 10, vec![HttpRange { start: 0, length: 6 }]), + T( + "bytes=0-9", + 10, + vec![HttpRange { + start: 0, + length: 10, + }], + ), + T( + "bytes=0-", + 10, + vec![HttpRange { + start: 0, + length: 10, + }], + ), + T( + "bytes=5-", + 10, + vec![HttpRange { + start: 5, + length: 5, + }], + ), + T( + "bytes=0-20", + 10, + vec![HttpRange { + start: 0, + length: 10, + }], + ), + T( + "bytes=15-,0-5", + 10, + vec![HttpRange { + start: 0, + length: 6, + }], + ), T( "bytes=1-2,5-", 10, - vec![HttpRange { start: 1, length: 2 }, HttpRange { start: 5, length: 5 }], + vec![ + HttpRange { + start: 1, + length: 2, + }, + HttpRange { + start: 5, + length: 5, + }, + ], ), T( "bytes=-2 , 7-", 11, - vec![HttpRange { start: 9, length: 2 }, HttpRange { start: 7, length: 4 }], + vec![ + HttpRange { + start: 9, + length: 2, + }, + HttpRange { + start: 7, + length: 4, + }, + ], ), T( "bytes=0-0 ,2-2, 7-", 11, vec![ - HttpRange { start: 0, length: 1 }, - HttpRange { start: 2, length: 1 }, - HttpRange { start: 7, length: 4 }, + HttpRange { + start: 0, + length: 1, + }, + HttpRange { + start: 2, + length: 1, + }, + HttpRange { + start: 7, + length: 4, + }, ], ), - T("bytes=-5", 10, vec![HttpRange { start: 5, length: 5 }]), - T("bytes=-15", 10, vec![HttpRange { start: 0, length: 10 }]), - T("bytes=0-499", 10000, vec![HttpRange { start: 0, length: 500 }]), + T( + "bytes=-5", + 10, + vec![HttpRange { + start: 5, + length: 5, + }], + ), + T( + "bytes=-15", + 10, + vec![HttpRange { + start: 0, + length: 10, + }], + ), + T( + "bytes=0-499", + 10000, + vec![HttpRange { + start: 0, + length: 500, + }], + ), T( "bytes=500-999", 10000, @@ -182,7 +265,16 @@ mod tests { T( "bytes=0-0,-1", 10000, - vec![HttpRange { start: 0, length: 1 }, HttpRange { start: 9999, length: 1 }], + vec![ + HttpRange { + start: 0, + length: 1, + }, + HttpRange { + start: 9999, + length: 1, + }, + ], ), T( "bytes=500-600,601-999", @@ -217,9 +309,18 @@ mod tests { "bytes= 1 -2 , 4- 5, 7 - 8 , ,,", 11, vec![ - HttpRange { start: 1, length: 2 }, - HttpRange { start: 4, length: 2 }, - HttpRange { start: 7, length: 2 }, + HttpRange { + start: 1, + length: 2, + }, + HttpRange { + start: 4, + length: 2, + }, + HttpRange { + start: 7, + length: 2, + }, ], ), ]; @@ -235,7 +336,12 @@ mod tests { if expected.is_empty() { continue; } else { - panic!("parse({}, {}) returned error {:?}", header, size, res.unwrap_err()); + panic!( + "parse({}, {}) returned error {:?}", + header, + size, + res.unwrap_err() + ); } } diff --git a/crates/core/src/http/request.rs b/crates/core/src/http/request.rs index 507fe6f1a..ba0bb5869 100644 --- a/crates/core/src/http/request.rs +++ b/crates/core/src/http/request.rs @@ -25,7 +25,9 @@ use crate::http::body::ReqBody; use crate::http::form::{FilePart, FormData}; use crate::http::{Mime, ParseError, Version}; use crate::routing::PathParams; -use crate::serde::{from_request, from_str_map, from_str_multi_map, from_str_multi_val, from_str_val}; +use crate::serde::{ + from_request, from_str_map, from_str_multi_map, from_str_multi_val, from_str_val, +}; use crate::Error; static SECURE_MAX_SIZE: RwLock = RwLock::new(64 * 1024); @@ -152,7 +154,9 @@ impl Request { for header in headers.get_all(http::header::COOKIE) { if let Ok(header) = header.to_str() { for cookie_str in header.split(';').map(|s| s.trim()) { - if let Ok(cookie) = Cookie::parse_encoded(cookie_str).map(|c| c.into_owned()) { + if let Ok(cookie) = + Cookie::parse_encoded(cookie_str).map(|c| c.into_owned()) + { cookie_jar.add_original(cookie); } } @@ -391,7 +395,12 @@ impl Request { /// /// When `overwrite` is set to `true`, If the header is already present, the value will be replaced. /// When `overwrite` is set to `false`, The new header is always appended to the request, even if the header already exists. - pub fn add_header(&mut self, name: N, value: V, overwrite: bool) -> crate::Result<&mut Self> + pub fn add_header( + &mut self, + name: N, + value: V, + overwrite: bool, + ) -> crate::Result<&mut Self> where N: IntoHeaderName, V: TryInto, @@ -596,7 +605,9 @@ impl Request { /// Get mutable queries reference. pub fn queries_mut(&mut self) -> &mut MultiMap { let _ = self.queries(); - self.queries.get_mut().expect("queries should be initialized") + self.queries + .get_mut() + .expect("queries should be initialized") } /// Get query value from queries. @@ -605,7 +616,9 @@ impl Request { where T: Deserialize<'de>, { - self.queries().get_vec(key).and_then(|vs| from_str_multi_val(vs).ok()) + self.queries() + .get_vec(key) + .and_then(|vs| from_str_multi_val(vs).ok()) } /// Get field data from form. @@ -667,7 +680,10 @@ impl Request { /// Get [`FilePart`] list reference from request. #[inline] pub async fn files<'a>(&'a mut self, key: &'a str) -> Option<&'a Vec> { - self.form_data().await.ok().and_then(|ps| ps.files.get_vec(key)) + self.form_data() + .await + .ok() + .and_then(|ps| ps.files.get_vec(key)) } /// Get [`FilePart`] list reference from request. @@ -738,7 +754,10 @@ impl Request { /// Extract request as type `T` from request's different parts. #[inline] - pub async fn extract_with_metadata<'de, T>(&'de mut self, metadata: &'de Metadata) -> Result + pub async fn extract_with_metadata<'de, T>( + &'de mut self, + metadata: &'de Metadata, + ) -> Result where T: Deserialize<'de> + Send, { @@ -804,22 +823,28 @@ impl Request { } /// Parse json body as type `T` from request with max size limit. #[inline] - pub async fn parse_json_with_max_size<'de, T>(&'de mut self, max_size: usize) -> Result + pub async fn parse_json_with_max_size<'de, T>( + &'de mut self, + max_size: usize, + ) -> Result where T: Deserialize<'de>, { let ctype = self.content_type(); if let Some(ctype) = ctype { if ctype.subtype() == mime::JSON { - return self.payload_with_max_size(max_size).await.and_then(|payload| { - // fix issue https://github.com/salvo-rs/salvo/issues/545 - let payload = if payload.is_empty() { - "null".as_bytes() - } else { - payload.as_ref() - }; - serde_json::from_slice::(payload).map_err(ParseError::SerdeJson) - }); + return self + .payload_with_max_size(max_size) + .await + .and_then(|payload| { + // fix issue https://github.com/salvo-rs/salvo/issues/545 + let payload = if payload.is_empty() { + "null".as_bytes() + } else { + payload.as_ref() + }; + serde_json::from_slice::(payload).map_err(ParseError::SerdeJson) + }); } } Err(ParseError::InvalidContentType) @@ -833,7 +858,8 @@ impl Request { { if let Some(ctype) = self.content_type() { if ctype.subtype() == mime::WWW_FORM_URLENCODED || ctype.subtype() == mime::FORM_DATA { - return from_str_multi_map(self.form_data().await?.fields.iter_all()).map_err(ParseError::Deserialize); + return from_str_multi_map(self.form_data().await?.fields.iter_all()) + .map_err(ParseError::Deserialize); } } Err(ParseError::InvalidContentType) @@ -849,18 +875,21 @@ impl Request { } /// Parse json body or form body as type `T` from request with max size. - pub async fn parse_body_with_max_size<'de, T>(&'de mut self, max_size: usize) -> Result + pub async fn parse_body_with_max_size<'de, T>( + &'de mut self, + max_size: usize, + ) -> Result where T: Deserialize<'de>, { if let Some(ctype) = self.content_type() { if ctype.subtype() == mime::WWW_FORM_URLENCODED || ctype.subtype() == mime::FORM_DATA { - return from_str_multi_map(self.form_data().await?.fields.iter_all()).map_err(ParseError::Deserialize); + return from_str_multi_map(self.form_data().await?.fields.iter_all()) + .map_err(ParseError::Deserialize); } else if ctype.subtype() == mime::JSON { - return self - .payload_with_max_size(max_size) - .await - .and_then(|body| serde_json::from_slice::(body).map_err(ParseError::SerdeJson)); + return self.payload_with_max_size(max_size).await.and_then(|body| { + serde_json::from_slice::(body).map_err(ParseError::SerdeJson) + }); } } Err(ParseError::InvalidContentType) @@ -913,14 +942,23 @@ mod tests { name: String, } let mut req = TestClient::get("http://127.0.0.1:5800/hello") - .json(&User { name: "jobs".into() }) + .json(&User { + name: "jobs".into(), + }) .build(); - assert_eq!(req.parse_json::().await.unwrap(), User { name: "jobs".into() }); + assert_eq!( + req.parse_json::().await.unwrap(), + User { + name: "jobs".into() + } + ); } #[tokio::test] async fn test_query() { - let req = TestClient::get("http://127.0.0.1:5801/hello?name=rust&name=25&name=a&name=2&weapons=98&weapons=gun") - .build(); + let req = TestClient::get( + "http://127.0.0.1:5801/hello?name=rust&name=25&name=a&name=2&weapons=98&weapons=gun", + ) + .build(); assert_eq!(req.queries().len(), 2); assert_eq!(req.query::("name").unwrap(), "rust"); assert_eq!(req.query::<&str>("name").unwrap(), "rust"); diff --git a/crates/core/src/http/response.rs b/crates/core/src/http/response.rs index 03d0afc2a..e7c4ec22f 100644 --- a/crates/core/src/http/response.rs +++ b/crates/core/src/http/response.rs @@ -135,7 +135,12 @@ impl Response { /// /// When `overwrite` is set to `true`, If the header is already present, the value will be replaced. /// When `overwrite` is set to `false`, The new header is always appended to the request, even if the header already exists. - pub fn add_header(&mut self, name: N, value: V, overwrite: bool) -> crate::Result<&mut Self> + pub fn add_header( + &mut self, + name: N, + value: V, + overwrite: bool, + ) -> crate::Result<&mut Self> where N: IntoHeaderName, V: TryInto, @@ -430,25 +435,33 @@ impl Response { chunks.push_back(data.into()); } ResBody::Hyper(_) => { - tracing::error!("current body's kind is `ResBody::Hyper`, it is not allowed to write bytes"); + tracing::error!( + "current body's kind is `ResBody::Hyper`, it is not allowed to write bytes" + ); return Err(Error::other( "current body's kind is `ResBody::Hyper`, it is not allowed to write bytes", )); } ResBody::Boxed(_) => { - tracing::error!("current body's kind is `ResBody::Boxed`, it is not allowed to write bytes"); + tracing::error!( + "current body's kind is `ResBody::Boxed`, it is not allowed to write bytes" + ); return Err(Error::other( "current body's kind is `ResBody::Boxed`, it is not allowed to write bytes", )); } ResBody::Stream(_) => { - tracing::error!("current body's kind is `ResBody::Stream`, it is not allowed to write bytes"); + tracing::error!( + "current body's kind is `ResBody::Stream`, it is not allowed to write bytes" + ); return Err(Error::other( "current body's kind is `ResBody::Stream`, it is not allowed to write bytes", )); } ResBody::Channel { .. } => { - tracing::error!("current body's kind is `ResBody::Channel`, it is not allowed to write bytes"); + tracing::error!( + "current body's kind is `ResBody::Channel`, it is not allowed to write bytes" + ); return Err(Error::other( "current body's kind is `ResBody::Channel`, it is not allowed to write bytes", )); diff --git a/crates/core/src/routing/filters/mod.rs b/crates/core/src/routing/filters/mod.rs index 23c3fdf50..12df81ea5 100644 --- a/crates/core/src/routing/filters/mod.rs +++ b/crates/core/src/routing/filters/mod.rs @@ -199,25 +199,37 @@ mod tests { let mut path_state = PathState::new("http://localhost/one"); assert!(one_filter.filter(&mut req, &mut path_state)); assert!(!two_filter.filter(&mut req, &mut path_state)); - assert!(one_filter.or_else(has_two).filter(&mut req, &mut path_state)); + assert!(one_filter + .or_else(has_two) + .filter(&mut req, &mut path_state)); assert!(one_filter.or(two_filter).filter(&mut req, &mut path_state)); - assert!(!one_filter.and_then(has_two).filter(&mut req, &mut path_state)); + assert!(!one_filter + .and_then(has_two) + .filter(&mut req, &mut path_state)); assert!(!one_filter.and(two_filter).filter(&mut req, &mut path_state)); let mut path_state = PathState::new("http://localhost/one/two"); assert!(one_filter.filter(&mut req, &mut path_state)); assert!(two_filter.filter(&mut req, &mut path_state)); - assert!(one_filter.or_else(has_two).filter(&mut req, &mut path_state)); + assert!(one_filter + .or_else(has_two) + .filter(&mut req, &mut path_state)); assert!(one_filter.or(two_filter).filter(&mut req, &mut path_state)); - assert!(one_filter.and_then(has_two).filter(&mut req, &mut path_state)); + assert!(one_filter + .and_then(has_two) + .filter(&mut req, &mut path_state)); assert!(one_filter.and(two_filter).filter(&mut req, &mut path_state)); let mut path_state = PathState::new("http://localhost/two"); assert!(!one_filter.filter(&mut req, &mut path_state)); assert!(two_filter.filter(&mut req, &mut path_state)); - assert!(one_filter.or_else(has_two).filter(&mut req, &mut path_state)); + assert!(one_filter + .or_else(has_two) + .filter(&mut req, &mut path_state)); assert!(one_filter.or(two_filter).filter(&mut req, &mut path_state)); - assert!(!one_filter.and_then(has_two).filter(&mut req, &mut path_state)); + assert!(!one_filter + .and_then(has_two) + .filter(&mut req, &mut path_state)); assert!(!one_filter.and(two_filter).filter(&mut req, &mut path_state)); } } diff --git a/crates/core/src/routing/filters/others.rs b/crates/core/src/routing/filters/others.rs index aeb625544..370035769 100644 --- a/crates/core/src/routing/filters/others.rs +++ b/crates/core/src/routing/filters/others.rs @@ -41,7 +41,10 @@ pub struct SchemeFilter { impl SchemeFilter { /// Create a new `SchemeFilter`. pub fn new(scheme: Scheme) -> Self { - Self { scheme, lack: false } + Self { + scheme, + lack: false, + } } /// Set lack value and return `Self`. pub fn lack(mut self, lack: bool) -> Self { @@ -52,7 +55,10 @@ impl SchemeFilter { impl Filter for SchemeFilter { #[inline] fn filter(&self, req: &mut Request, _state: &mut PathState) -> bool { - req.uri().scheme().map(|s| s == &self.scheme).unwrap_or(self.lack) + req.uri() + .scheme() + .map(|s| s == &self.scheme) + .unwrap_or(self.lack) } } impl fmt::Debug for SchemeFilter { diff --git a/crates/core/src/routing/filters/path.rs b/crates/core/src/routing/filters/path.rs index d57d0b03b..18957a32b 100644 --- a/crates/core/src/routing/filters/path.rs +++ b/crates/core/src/routing/filters/path.rs @@ -37,8 +37,14 @@ pub trait WispBuilder: Send + Sync { type WispBuilderMap = RwLock>>>; static WISP_BUILDERS: LazyLock = LazyLock::new(|| { let mut map: HashMap>> = HashMap::with_capacity(8); - map.insert("num".into(), Arc::new(Box::new(CharsWispBuilder::new(is_num)))); - map.insert("hex".into(), Arc::new(Box::new(CharsWispBuilder::new(is_hex)))); + map.insert( + "num".into(), + Arc::new(Box::new(CharsWispBuilder::new(is_num))), + ); + map.insert( + "hex".into(), + Arc::new(Box::new(CharsWispBuilder::new(is_hex))), + ); RwLock::new(map) }); @@ -170,7 +176,10 @@ impl WispBuilder for CharsWispBuilder { } .into()); } - let ps = args[0].splitn(2, "..").map(|s| s.trim()).collect::>(); + let ps = args[0] + .splitn(2, "..") + .map(|s| s.trim()) + .collect::>(); let (min_width, max_width) = if ps.is_empty() { (1, None) } else { @@ -289,10 +298,14 @@ pub struct CombWisp(pub Vec); impl CombWisp { #[inline] fn find_const_wisp_from(&self, index: usize) -> Option<(usize, &ConstWisp)> { - self.0.iter().skip(index).enumerate().find_map(|(i, wisp)| match wisp { - WispKind::Const(wisp) => Some((i + index, wisp)), - _ => None, - }) + self.0 + .iter() + .skip(index) + .enumerate() + .find_map(|(i, wisp)| match wisp { + WispKind::Const(wisp) => Some((i + index, wisp)), + _ => None, + }) } } impl PathWisp for CombWisp { @@ -327,7 +340,8 @@ impl PathWisp for CombWisp { } if online_all_matched { state.cursor.1 = 0; - if let Some((next_const_index, next_const_wisp)) = self.find_const_wisp_from(index) { + if let Some((next_const_index, next_const_wisp)) = self.find_const_wisp_from(index) + { if next_const_index == self.0.len() - 1 { if offline.ends_with(&next_const_wisp.0) { if index == next_const_index { @@ -347,7 +361,9 @@ impl PathWisp for CombWisp { } else { return false; } - } else if let Some((new_online, new_offline)) = offline.split_once(&next_const_wisp.0) { + } else if let Some((new_online, new_offline)) = + offline.split_once(&next_const_wisp.0) + { if next_const_index == index { if !new_online.is_empty() { return false; @@ -380,7 +396,10 @@ impl PathWisp for CombWisp { return false; } } - *(state.parts.get_mut(row).expect("path state part should be exists")) = origin_part; + *(state + .parts + .get_mut(row) + .expect("path state part should be exists")) = origin_part; offline.is_empty() } fn validate(&self) -> Result<(), String> { @@ -415,7 +434,12 @@ impl PathWisp for NamedWisp { fn detect<'a>(&self, state: &mut PathState) -> bool { if self.0.starts_with('*') { let rest = state.all_rest().unwrap_or_default(); - if self.0.starts_with("*?") && rest.trim_start_matches('/').trim_end_matches('/').contains('/') { + if self.0.starts_with("*?") + && rest + .trim_start_matches('/') + .trim_end_matches('/') + .contains('/') + { return false; } if !rest.is_empty() || !self.0.starts_with("*+") { @@ -465,7 +489,12 @@ impl PathWisp for RegexWisp { fn detect<'a>(&self, state: &mut PathState) -> bool { if self.name.starts_with('*') { let rest = state.all_rest().unwrap_or_default(); - if self.name.starts_with("*?") && rest.trim_start_matches('/').trim_end_matches('/').contains('/') { + if self.name.starts_with("*?") + && rest + .trim_start_matches('/') + .trim_end_matches('/') + .contains('/') + { return false; } if !rest.is_empty() || !self.name.starts_with("*+") { @@ -667,7 +696,8 @@ impl PathParser { let mut wisps: Vec = vec![]; while ch != '/' { if ch == '<' { - self.next(true).ok_or_else(|| "char is needed after <".to_owned())?; + self.next(true) + .ok_or_else(|| "char is needed after <".to_owned())?; let name = self.scan_ident()?; if name.is_empty() { return Err("name is empty string".to_owned()); @@ -685,13 +715,15 @@ impl PathParser { //start to scan fn part let sign = self.scan_ident()?; self.skip_blanks(); - let lb = self.curr().ok_or_else(|| "path ended unexpectedly".to_owned())?; + let lb = self + .curr() + .ok_or_else(|| "path ended unexpectedly".to_owned())?; let args = if lb == '[' || lb == '(' { let rb = if lb == '[' { ']' } else { ')' }; let mut args = "".to_owned(); - ch = self - .next(true) - .ok_or_else(|| "current position is out of index when scan ident".to_owned())?; + ch = self.next(true).ok_or_else(|| { + "current position is out of index when scan ident".to_owned() + })?; while ch != rb { args.push(ch); if let Some(c) = self.next(false) { @@ -720,7 +752,9 @@ impl PathParser { let builders = WISP_BUILDERS.read(); let builder = builders .get(&sign) - .ok_or_else(|| format!("WISP_BUILDERS does not contains fn part with sign {sign}"))? + .ok_or_else(|| { + format!("WISP_BUILDERS does not contains fn part with sign {sign}") + })? .clone(); wisps.push(builder.build(name, sign, args)?); @@ -771,7 +805,10 @@ impl PathParser { loop { self.skip_slashes(); if self.curr().map(|c| c == '/').unwrap_or(false) { - return Err(format!("'/' is not allowed after '/' at offset `{}`", self.offset)); + return Err(format!( + "'/' is not allowed after '/' at offset `{}`", + self.offset + )); } let mut scaned = self.scan_wisps()?; if scaned.len() > 1 { @@ -896,7 +933,10 @@ impl PathFilter { panic!("{}, raw_value: {}", e, raw_value); } }; - PathFilter { raw_value, path_wisps } + PathFilter { + raw_value, + path_wisps, + } } /// Register new path wisp builder. #[inline] @@ -911,7 +951,10 @@ impl PathFilter { #[inline] pub fn register_wisp_regex(name: impl Into, regex: Regex) { let mut builders = WISP_BUILDERS.write(); - builders.insert(name.into(), Arc::new(Box::new(RegexWispBuilder::new(regex)))); + builders.insert( + name.into(), + Arc::new(Box::new(RegexWispBuilder::new(regex))), + ); } /// Detect is that path is match. pub fn detect(&self, state: &mut PathState) -> bool { @@ -956,7 +999,10 @@ mod tests { #[test] fn test_parse_multi_const() { let segments = PathParser::new("/hello/world").parse().unwrap(); - assert_eq!(format!("{:?}", segments), r#"[ConstWisp("hello"), ConstWisp("world")]"#); + assert_eq!( + format!("{:?}", segments), + r#"[ConstWisp("hello"), ConstWisp("world")]"# + ); } #[test] fn test_parse_single_regex() { @@ -992,7 +1038,9 @@ mod tests { } #[test] fn test_parse_single_regex_with_prefix_and_suffix() { - let segments = PathParser::new(r"/prefixsuffix.png").parse().unwrap(); + let segments = PathParser::new(r"/prefixsuffix.png") + .parse() + .unwrap(); assert_eq!( format!("{:?}", segments), r#"[CombWisp([ConstWisp("prefix"), RegexWisp { name: "abc", regex: Regex("\\d+") }, ConstWisp("suffix.png")])]"# @@ -1000,7 +1048,9 @@ mod tests { } #[test] fn test_parse_dot_after_param() { - let segments = PathParser::new(r"//show/.bu").parse().unwrap(); + let segments = PathParser::new(r"//show/.bu") + .parse() + .unwrap(); assert_eq!( format!("{:?}", segments), r#"[NamedWisp("pid"), ConstWisp("show"), CombWisp([NamedWisp("table_name"), ConstWisp(".bu")])]"# @@ -1008,7 +1058,9 @@ mod tests { } #[test] fn test_parse_multi_regex() { - let segments = PathParser::new(r"/first/prefix").parse().unwrap(); + let segments = PathParser::new(r"/first/prefix") + .parse() + .unwrap(); assert_eq!( format!("{:?}", segments), r#"[CombWisp([ConstWisp("first"), NamedWisp("id")]), CombWisp([ConstWisp("prefix"), RegexWisp { name: "abc", regex: Regex("\\d+") }])]"# @@ -1016,7 +1068,9 @@ mod tests { } #[test] fn test_parse_multi_regex_with_prefix() { - let segments = PathParser::new(r"/first/prefix").parse().unwrap(); + let segments = PathParser::new(r"/first/prefix") + .parse() + .unwrap(); assert_eq!( format!("{:?}", segments), r#"[CombWisp([ConstWisp("first"), NamedWisp("id")]), CombWisp([ConstWisp("prefix"), RegexWisp { name: "abc", regex: Regex("\\d+") }])]"# @@ -1024,7 +1078,9 @@ mod tests { } #[test] fn test_parse_multi_regex_with_suffix() { - let segments = PathParser::new(r"/first/prefix").parse().unwrap(); + let segments = PathParser::new(r"/first/prefix") + .parse() + .unwrap(); assert_eq!( format!("{:?}", segments), r#"[CombWisp([ConstWisp("first"), RegexWisp { name: "id", regex: Regex("\\d+") }]), CombWisp([ConstWisp("prefix"), RegexWisp { name: "abc", regex: Regex("\\d+") }])]"# @@ -1032,7 +1088,9 @@ mod tests { } #[test] fn test_parse_multi_regex_with_prefix_and_suffix() { - let segments = PathParser::new(r"/first/prefixext").parse().unwrap(); + let segments = PathParser::new(r"/first/prefixext") + .parse() + .unwrap(); assert_eq!( format!("{:?}", segments), r#"[CombWisp([ConstWisp("first"), NamedWisp("id")]), CombWisp([ConstWisp("prefix"), RegexWisp { name: "abc", regex: Regex("\\d+") }, ConstWisp("ext")])]"# @@ -1143,16 +1201,22 @@ mod tests { #[test] fn test_parse_rest2_failed() { - assert!(PathParser::new(r"/first<*ext>/<**rest>").parse().is_err()); + assert!(PathParser::new(r"/first<*ext>/<**rest>") + .parse() + .is_err()); } #[test] fn test_parse_rest_failed1() { - assert!(PathParser::new(r"/firstext2/<**rest>").parse().is_err()); + assert!(PathParser::new(r"/firstext2/<**rest>") + .parse() + .is_err()); } #[test] fn test_parse_rest_failed2() { - assert!(PathParser::new(r"/firstext2/<**rest>wefwe").parse().is_err()); + assert!(PathParser::new(r"/firstext2/<**rest>wefwe") + .parse() + .is_err()); } #[test] fn test_parse_many_slashes() { diff --git a/crates/core/src/routing/mod.rs b/crates/core/src/routing/mod.rs index cbafb092e..7c5d8382d 100644 --- a/crates/core/src/routing/mod.rs +++ b/crates/core/src/routing/mod.rs @@ -589,7 +589,12 @@ impl FlowCtrl { /// /// **NOTE**: If response status code is error or is redirection, all reset handlers will be skipped. #[inline] - pub async fn call_next(&mut self, req: &mut Request, depot: &mut Depot, res: &mut Response) -> bool { + pub async fn call_next( + &mut self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ) -> bool { if self.catching.is_none() { self.catching = Some(res.is_stamped()); } @@ -669,7 +674,9 @@ mod tests { .unwrap() } - assert!(access(&service, "127.0.0.1").await.contains("404: Not Found")); + assert!(access(&service, "127.0.0.1") + .await + .contains("404: Not Found")); assert_eq!(access(&service, "localhost").await, "Hello World"); } } diff --git a/crates/core/src/routing/router.rs b/crates/core/src/routing/router.rs index 8422b161b..eaad92da2 100644 --- a/crates/core/src/routing/router.rs +++ b/crates/core/src/routing/router.rs @@ -171,7 +171,10 @@ impl Router { H: Handler, F: Fn(&Request, &Depot) -> bool + Send + Sync + 'static, { - self.hoops.push(Arc::new(WhenHoop { inner: hoop, filter })); + self.hoops.push(Arc::new(WhenHoop { + inner: hoop, + filter, + })); self } @@ -403,7 +406,10 @@ mod tests { let router = Router::default() .push( Router::with_path("users") - .push(Router::with_path("").push(Router::with_path("emails").get(fake_handler))) + .push( + Router::with_path("") + .push(Router::with_path("emails").get(fake_handler)), + ) .push( Router::with_path("/articles/") .get(fake_handler) @@ -417,7 +423,11 @@ mod tests { .get(fake_handler) .delete(fake_handler), ) - .push(Router::with_path("").get(fake_handler).delete(fake_handler)), + .push( + Router::with_path("") + .get(fake_handler) + .delete(fake_handler), + ), ); assert_eq!( format!("{:?}", router), @@ -441,10 +451,10 @@ mod tests { } #[test] fn test_router_detect1() { - let router = Router::default().push( - Router::with_path("users") - .push(Router::with_path("").push(Router::with_path("emails").get(fake_handler))), - ); + let router = + Router::default().push(Router::with_path("users").push( + Router::with_path("").push(Router::with_path("emails").get(fake_handler)), + )); let mut req = TestClient::get("http://local.host/users/12/emails").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -454,10 +464,9 @@ mod tests { fn test_router_detect2() { let router = Router::new() .push(Router::with_path("users").push(Router::with_path("").get(fake_handler))) - .push( - Router::with_path("users") - .push(Router::with_path("").push(Router::with_path("emails").get(fake_handler))), - ); + .push(Router::with_path("users").push( + Router::with_path("").push(Router::with_path("emails").get(fake_handler)), + )); let mut req = TestClient::get("http://local.host/users/12/emails").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -467,8 +476,10 @@ mod tests { fn test_router_detect3() { let router = Router::new().push( Router::with_path("users").push( - Router::with_path(r"") - .push(Router::new().push(Router::with_path("facebook/insights/<**rest>").goal(fake_handler))), + Router::with_path(r"").push( + Router::new() + .push(Router::with_path("facebook/insights/<**rest>").goal(fake_handler)), + ), ), ); let mut req = TestClient::get("http://local.host/users/12/facebook/insights").build(); @@ -486,8 +497,10 @@ mod tests { fn test_router_detect4() { let router = Router::new().push( Router::with_path("users").push( - Router::with_path(r"") - .push(Router::new().push(Router::with_path("facebook/insights/<*+rest>").goal(fake_handler))), + Router::with_path(r"").push( + Router::new() + .push(Router::with_path("facebook/insights/<*+rest>").goal(fake_handler)), + ), ), ); let mut req = TestClient::get("http://local.host/users/12/facebook/insights").build(); @@ -503,12 +516,16 @@ mod tests { } #[test] fn test_router_detect5() { - let router = - Router::new().push(Router::with_path("users").push(Router::with_path(r"").push( - Router::new().push( - Router::with_path("facebook/insights").push(Router::with_path("<**rest>").goal(fake_handler)), + let router = Router::new().push( + Router::with_path("users").push( + Router::with_path(r"").push( + Router::new().push( + Router::with_path("facebook/insights") + .push(Router::with_path("<**rest>").goal(fake_handler)), + ), ), - ))); + ), + ); let mut req = TestClient::get("http://local.host/users/12/facebook/insights").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -522,12 +539,16 @@ mod tests { } #[test] fn test_router_detect6() { - let router = - Router::new().push(Router::with_path("users").push(Router::with_path(r"").push( - Router::new().push( - Router::with_path("facebook/insights").push(Router::new().path("<*+rest>").goal(fake_handler)), + let router = Router::new().push( + Router::with_path("users").push( + Router::with_path(r"").push( + Router::new().push( + Router::with_path("facebook/insights") + .push(Router::new().path("<*+rest>").goal(fake_handler)), + ), ), - ))); + ), + ); let mut req = TestClient::get("http://local.host/users/12/facebook/insights").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -540,25 +561,32 @@ mod tests { } #[test] fn test_router_detect_utf8() { - let router = - Router::new().push(Router::with_path("用户").push(Router::with_path(r"").push( - Router::new().push( - Router::with_path("facebook/insights").push(Router::with_path("<*+rest>").goal(fake_handler)), + let router = Router::new().push( + Router::with_path("用户").push( + Router::with_path(r"").push( + Router::new().push( + Router::with_path("facebook/insights") + .push(Router::with_path("<*+rest>").goal(fake_handler)), + ), ), - ))); - let mut req = TestClient::get("http://local.host/%E7%94%A8%E6%88%B7/12/facebook/insights").build(); + ), + ); + let mut req = + TestClient::get("http://local.host/%E7%94%A8%E6%88%B7/12/facebook/insights").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); assert!(matched.is_none()); - let mut req = TestClient::get("http://local.host/%E7%94%A8%E6%88%B7/12/facebook/insights/23").build(); + let mut req = + TestClient::get("http://local.host/%E7%94%A8%E6%88%B7/12/facebook/insights/23").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); assert!(matched.is_some()); } #[test] fn test_router_detect9() { - let router = Router::new().push(Router::with_path("users//").goal(fake_handler)); + let router = Router::new() + .push(Router::with_path("users//").goal(fake_handler)); let mut req = TestClient::get("http://local.host/users/12/m.jpg").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -571,7 +599,8 @@ mod tests { } #[test] fn test_router_detect10() { - let router = Router::new().push(Router::with_path(r"users/<*sub:/(images|css)/.+/>").goal(fake_handler)); + let router = Router::new() + .push(Router::with_path(r"users/<*sub:/(images|css)/.+/>").goal(fake_handler)); let mut req = TestClient::get("http://local.host/users/12/m.jpg").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -584,8 +613,9 @@ mod tests { } #[test] fn test_router_detect11() { - let router = - Router::new().push(Router::with_path(r"avatars/x.").goal(fake_handler)); + let router = Router::new().push( + Router::with_path(r"avatars/x.").goal(fake_handler), + ); let mut req = TestClient::get("http://local.host/avatars/321x641f.webp").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); @@ -598,9 +628,12 @@ mod tests { } #[test] fn test_router_detect12() { - let router = Router::new().push(Router::with_path("/.well-known/acme-challenge/").goal(fake_handler)); + let router = Router::new() + .push(Router::with_path("/.well-known/acme-challenge/").goal(fake_handler)); - let mut req = TestClient::get("http://local.host/.well-known/acme-challenge/q1XXrxIx79uXNl3I").build(); + let mut req = + TestClient::get("http://local.host/.well-known/acme-challenge/q1XXrxIx79uXNl3I") + .build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); assert!(matched.is_some()); @@ -611,11 +644,13 @@ mod tests { let router = Router::new() .path("user/") .get(fake_handler); - let mut req = TestClient::get("http://local.host/user/726d694c-7af0-4bb0-9d22-706f7e38641e").build(); + let mut req = + TestClient::get("http://local.host/user/726d694c-7af0-4bb0-9d22-706f7e38641e").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); assert!(matched.is_some()); - let mut req = TestClient::get("http://local.host/user/726d694c-7af0-4bb0-9d22-706f7e386e").build(); + let mut req = + TestClient::get("http://local.host/user/726d694c-7af0-4bb0-9d22-706f7e386e").build(); let mut path_state = PathState::new(req.uri().path()); let matched = router.detect(&mut req, &mut path_state); assert!(matched.is_none()); diff --git a/crates/core/src/serde/mod.rs b/crates/core/src/serde/mod.rs index ab5c1bf34..d1b89b4d7 100644 --- a/crates/core/src/serde/mod.rs +++ b/crates/core/src/serde/mod.rs @@ -3,7 +3,8 @@ use std::hash::Hash; pub use serde::de::value::{Error as ValError, MapDeserializer, SeqDeserializer}; use serde::de::{ - Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error as DeError, IntoDeserializer, VariantAccess, Visitor, + Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error as DeError, IntoDeserializer, + VariantAccess, Visitor, }; use serde::forward_to_deserialize_any; @@ -18,7 +19,9 @@ where K: Into>, V: Into>, { - let iter = input.into_iter().map(|(k, v)| (CowValue(k.into()), CowValue(v.into()))); + let iter = input + .into_iter() + .map(|(k, v)| (CowValue(k.into()), CowValue(v.into()))); T::deserialize(MapDeserializer::new(iter)) } @@ -31,9 +34,12 @@ where C: IntoIterator + 'de, V: Into> + std::cmp::Eq + 'de, { - let iter = input - .into_iter() - .map(|(k, v)| (CowValue(k.into()), VecValue(v.into_iter().map(|v| CowValue(v.into()))))); + let iter = input.into_iter().map(|(k, v)| { + ( + CowValue(k.into()), + VecValue(v.into_iter().map(|v| CowValue(v.into()))), + ) + }); T::deserialize(MapDeserializer::new(iter)) } @@ -133,7 +139,11 @@ impl<'de> VariantAccess<'de> for UnitOnlyVariantAccess { } #[inline] - fn struct_variant(self, _fields: &'static [&'static str], _visitor: V) -> Result + fn struct_variant( + self, + _fields: &'static [&'static str], + _visitor: V, + ) -> Result where V: Visitor<'de>, { @@ -187,7 +197,11 @@ impl<'de> Deserializer<'de> for CowValue<'de> { } #[inline] - fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result where V: Visitor<'de>, { @@ -283,7 +297,11 @@ where } #[inline] - fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result where V: Visitor<'de>, { @@ -291,7 +309,12 @@ where } #[inline] - fn deserialize_tuple_struct(self, _name: &'static str, _len: usize, visitor: V) -> Result + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result where V: Visitor<'de>, { diff --git a/crates/core/src/serde/request.rs b/crates/core/src/serde/request.rs index ced0c2683..feb4e2764 100644 --- a/crates/core/src/serde/request.rs +++ b/crates/core/src/serde/request.rs @@ -17,7 +17,10 @@ use crate::Request; use super::{CowValue, VecValue}; -pub async fn from_request<'de, T>(req: &'de mut Request, metadata: &'de Metadata) -> Result +pub async fn from_request<'de, T>( + req: &'de mut Request, + metadata: &'de Metadata, +) -> Result where T: Deserialize<'de>, { @@ -77,7 +80,10 @@ pub(crate) struct RequestDeserializer<'de> { impl<'de> RequestDeserializer<'de> { /// Construct a new `RequestDeserializer`. - pub(crate) fn new(request: &'de Request, metadata: &'de Metadata) -> Result, ParseError> { + pub(crate) fn new( + request: &'de Request, + metadata: &'de Metadata, + ) -> Result, ParseError> { let mut payload = None; if metadata.has_body_required() { @@ -90,7 +96,9 @@ impl<'de> RequestDeserializer<'de> { if let Some(data) = request.payload.get() { if !data.is_empty() { // https://github.com/serde-rs/json/issues/903 - payload = match serde_json::from_slice::>(data) { + payload = match serde_json::from_slice::>( + data, + ) { Ok(map) => Some(Payload::JsonMap(map)), Err(e) => { tracing::warn!(error = ?e, "`RequestDeserializer` serde parse json payload failed"); @@ -247,7 +255,8 @@ impl<'de> RequestDeserializer<'de> { } } if let Some(value) = value { - self.field_vec_value = Some(value.iter().map(|v| CowValue(v.into())).collect()); + self.field_vec_value = + Some(value.iter().map(|v| CowValue(v.into())).collect()); self.field_source = Some(source); return true; } @@ -356,7 +365,9 @@ impl<'de> RequestDeserializer<'de> { } } if let Some(value) = value { - self.field_vec_value = Some(value.iter().map(|v| CowValue(Cow::from(v))).collect()); + self.field_vec_value = Some( + value.iter().map(|v| CowValue(Cow::from(v))).collect(), + ); self.field_source = Some(source); return true; } @@ -443,7 +454,11 @@ impl<'de> de::MapAccess<'de> for RequestDeserializer<'de> { } #[inline] - fn next_entry_seed(&mut self, kseed: TK, vseed: TV) -> Result, Self::Error> + fn next_entry_seed( + &mut self, + kseed: TK, + vseed: TV, + ) -> Result, Self::Error> where TK: de::DeserializeSeed<'de>, TV: de::DeserializeSeed<'de>, @@ -699,7 +714,10 @@ mod tests { data, RequestData { p2: "921", - user: User { name: "chris", age: 20 } + user: User { + name: "chris", + age: 20 + } } ); } @@ -712,8 +730,10 @@ mod tests { #[salvo(extract(rename = "currAge"))] curr_age: usize, } - let mut req = - TestClient::get("http://127.0.0.1:5800/test/1234/param2v?full-name=chris+young&currAge=20").build(); + let mut req = TestClient::get( + "http://127.0.0.1:5800/test/1234/param2v?full-name=chris+young&currAge=20", + ) + .build(); let data: RequestData = req.extract().await.unwrap(); assert_eq!( data, @@ -733,8 +753,10 @@ mod tests { #[salvo(extract(rename = "currAge"))] curr_age: usize, } - let mut req = - TestClient::get("http://127.0.0.1:5800/test/1234/param2v?full-name=chris+young&currAge=20").build(); + let mut req = TestClient::get( + "http://127.0.0.1:5800/test/1234/param2v?full-name=chris+young&currAge=20", + ) + .build(); let data: RequestData = req.extract().await.unwrap(); assert_eq!( data, @@ -754,8 +776,10 @@ mod tests { #[salvo(extract(rename = "currAge"))] curr_age: usize, } - let mut req = - TestClient::get("http://127.0.0.1:5800/test/1234/param2v?full-name=chris+young&currAge=20").build(); + let mut req = TestClient::get( + "http://127.0.0.1:5800/test/1234/param2v?full-name=chris+young&currAge=20", + ) + .build(); let data: RequestData = req.extract().await.unwrap(); assert_eq!( data, diff --git a/crates/core/src/service.rs b/crates/core/src/service.rs index f21dc1e63..78e6d6139 100644 --- a/crates/core/src/service.rs +++ b/crates/core/src/service.rs @@ -95,7 +95,10 @@ impl Service { H: Handler, F: Fn(&Request, &Depot) -> bool + Send + Sync + 'static, { - self.hoops.push(Arc::new(WhenHoop { inner: hoop, filter })); + self.hoops.push(Arc::new(WhenHoop { + inner: hoop, + filter, + })); self } @@ -257,7 +260,10 @@ impl HyperHandler { "http response content type header not set" ); } - if Method::HEAD != *req.method() && (res.body.is_none() || res.body.is_error()) && has_error { + if Method::HEAD != *req.method() + && (res.body.is_none() || res.body.is_error()) + && has_error + { if let Some(catcher) = catcher { catcher.catch(&mut req, &mut depot, &mut res).await; } else { @@ -272,22 +278,23 @@ impl HyperHandler { { use bytes::Bytes; use parking_lot::Mutex; - if let Some(session) = req - .extensions - .remove::>() + if let Some(session) = + req.extensions.remove::>() { res.extensions.insert(Arc::new(session)); } - if let Some(conn) = req - .extensions - .remove::>>() - { + if let Some(conn) = req.extensions.remove::, + >>() { res.extensions.insert(Arc::new(conn)); } - if let Some(stream) = req - .extensions - .remove::, Bytes>>() - { + if let Some(stream) = req.extensions.remove::, + Bytes, + >>() { res.extensions.insert(Arc::new(stream)); } } @@ -310,7 +317,11 @@ where #[cfg(not(feature = "fix-http1-request-uri"))] req: HyperRequest, #[cfg(feature = "fix-http1-request-uri")] mut req: HyperRequest, ) -> Self::Future { - let scheme = req.uri().scheme().cloned().unwrap_or_else(|| self.http_scheme.clone()); + let scheme = req + .uri() + .scheme() + .cloned() + .unwrap_or_else(|| self.http_scheme.clone()); // https://github.com/hyperium/hyper/issues/1310 #[cfg(feature = "fix-http1-request-uri")] if req.uri().scheme().is_none() { @@ -343,7 +354,12 @@ mod tests { #[tokio::test] async fn test_service() { #[handler] - async fn before1(req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn before1( + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { res.render(Text::Plain("before1")); if req.query::("b").unwrap_or_default() == "1" { ctrl.skip_rest(); @@ -352,7 +368,12 @@ mod tests { } } #[handler] - async fn before2(req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn before2( + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { res.render(Text::Plain("before2")); if req.query::("b").unwrap_or_default() == "2" { ctrl.skip_rest(); @@ -361,7 +382,12 @@ mod tests { } } #[handler] - async fn before3(req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn before3( + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { res.render(Text::Plain("before3")); if req.query::("b").unwrap_or_default() == "3" { ctrl.skip_rest(); diff --git a/crates/core/src/writing/json.rs b/crates/core/src/writing/json.rs index 51e4690c8..df989698c 100644 --- a/crates/core/src/writing/json.rs +++ b/crates/core/src/writing/json.rs @@ -63,11 +63,15 @@ mod tests { } #[handler] async fn test() -> Json { - Json(User { name: "jobs".into() }) + Json(User { + name: "jobs".into(), + }) } let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), r#"{"name":"jobs"}"#); assert_eq!( res.headers().get("content-type").unwrap(), diff --git a/crates/core/src/writing/mod.rs b/crates/core/src/writing/mod.rs index 699ed001b..86956fb4a 100644 --- a/crates/core/src/writing/mod.rs +++ b/crates/core/src/writing/mod.rs @@ -97,24 +97,30 @@ impl Scribe for StatusCode { impl Scribe for &'static str { #[inline] fn render(self, res: &mut Response) { - res.headers_mut() - .insert(CONTENT_TYPE, HeaderValue::from_static("text/plain; charset=utf-8")); + res.headers_mut().insert( + CONTENT_TYPE, + HeaderValue::from_static("text/plain; charset=utf-8"), + ); res.write_body(self).ok(); } } impl<'a> Scribe for &'a String { #[inline] fn render(self, res: &mut Response) { - res.headers_mut() - .insert(CONTENT_TYPE, HeaderValue::from_static("text/plain; charset=utf-8")); + res.headers_mut().insert( + CONTENT_TYPE, + HeaderValue::from_static("text/plain; charset=utf-8"), + ); res.write_body(self.as_bytes().to_vec()).ok(); } } impl Scribe for String { #[inline] fn render(self, res: &mut Response) { - res.headers_mut() - .insert(CONTENT_TYPE, HeaderValue::from_static("text/plain; charset=utf-8")); + res.headers_mut().insert( + CONTENT_TYPE, + HeaderValue::from_static("text/plain; charset=utf-8"), + ); res.write_body(self).ok(); } } @@ -158,9 +164,14 @@ mod tests { let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), "hello"); - assert_eq!(res.headers().get("content-type").unwrap(), "text/plain; charset=utf-8"); + assert_eq!( + res.headers().get("content-type").unwrap(), + "text/plain; charset=utf-8" + ); } #[tokio::test] @@ -171,8 +182,13 @@ mod tests { } let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), "hello"); - assert_eq!(res.headers().get("content-type").unwrap(), "text/plain; charset=utf-8"); + assert_eq!( + res.headers().get("content-type").unwrap(), + "text/plain; charset=utf-8" + ); } } diff --git a/crates/core/src/writing/redirect.rs b/crates/core/src/writing/redirect.rs index 65f4b267c..54741fe4a 100644 --- a/crates/core/src/writing/redirect.rs +++ b/crates/core/src/writing/redirect.rs @@ -78,7 +78,10 @@ impl Redirect { } /// Create a new [`Redirect`] that uses a status code. - pub fn with_status_code(status_code: StatusCode, uri: impl TryInto) -> Result { + pub fn with_status_code( + status_code: StatusCode, + uri: impl TryInto, + ) -> Result { if !status_code.is_redirection() { return Err(Error::other("not a redirection status code")); } @@ -89,7 +92,8 @@ impl Redirect { .try_into() .map_err(|_| Error::other("It isn't a valid URI")) .and_then(|uri| { - HeaderValue::try_from(uri.to_string()).map_err(|_| Error::other("URI isn't a valid header value")) + HeaderValue::try_from(uri.to_string()) + .map_err(|_| Error::other("URI isn't a valid header value")) })?, }) } @@ -98,7 +102,10 @@ impl Redirect { impl Scribe for Redirect { #[inline] fn render(self, res: &mut Response) { - let Self { status_code, location } = self; + let Self { + status_code, + location, + } = self; res.status_code(status_code); res.headers_mut().insert(LOCATION, location); } diff --git a/crates/core/src/writing/seek.rs b/crates/core/src/writing/seek.rs index e8329eda1..8c8324be5 100644 --- a/crates/core/src/writing/seek.rs +++ b/crates/core/src/writing/seek.rs @@ -64,9 +64,10 @@ where // check preconditions let precondition_failed = if !any_match(self.etag.as_ref(), req_headers) { true - } else if let (Some(last_modified), Some(since)) = - (&self.last_modified, req_headers.typed_get::()) - { + } else if let (Some(last_modified), Some(since)) = ( + &self.last_modified, + req_headers.typed_get::(), + ) { !since.precondition_passes(*last_modified) } else { false @@ -77,9 +78,10 @@ where true } else if req_headers.contains_key(IF_NONE_MATCH) { false - } else if let (Some(last_modified), Some(since)) = - (&self.last_modified, req_headers.typed_get::()) - { + } else if let (Some(last_modified), Some(since)) = ( + &self.last_modified, + req_headers.typed_get::(), + ) { !since.is_modified(*last_modified) } else { false @@ -103,7 +105,8 @@ where length = range[0].length; offset = range[0].start; } else { - res.headers_mut().typed_insert(ContentRange::unsatisfied_bytes(length)); + res.headers_mut() + .typed_insert(ContentRange::unsatisfied_bytes(length)); res.status_code(StatusCode::RANGE_NOT_SATISFIABLE); return; }; diff --git a/crates/core/src/writing/text.rs b/crates/core/src/writing/text.rs index 8f9f00da8..553fc38bc 100644 --- a/crates/core/src/writing/text.rs +++ b/crates/core/src/writing/text.rs @@ -44,16 +44,40 @@ where { fn set_header(self, res: &mut Response) -> C { let (ctype, content) = match self { - Self::Plain(content) => (HeaderValue::from_static("text/plain; charset=utf-8"), content), - Self::Json(content) => (HeaderValue::from_static("application/json; charset=utf-8"), content), - Self::Xml(content) => (HeaderValue::from_static("application/xml; charset=utf-8"), content), - Self::Html(content) => (HeaderValue::from_static("text/html; charset=utf-8"), content), - Self::Js(content) => (HeaderValue::from_static("text/javascript; charset=utf-8"), content), + Self::Plain(content) => ( + HeaderValue::from_static("text/plain; charset=utf-8"), + content, + ), + Self::Json(content) => ( + HeaderValue::from_static("application/json; charset=utf-8"), + content, + ), + Self::Xml(content) => ( + HeaderValue::from_static("application/xml; charset=utf-8"), + content, + ), + Self::Html(content) => ( + HeaderValue::from_static("text/html; charset=utf-8"), + content, + ), + Self::Js(content) => ( + HeaderValue::from_static("text/javascript; charset=utf-8"), + content, + ), Self::Css(content) => (HeaderValue::from_static("text/css; charset=utf-8"), content), Self::Csv(content) => (HeaderValue::from_static("text/csv; charset=utf-8"), content), - Self::Atom(content) => (HeaderValue::from_static("application/atom+xml; charset=utf-8"), content), - Self::Rss(content) => (HeaderValue::from_static("application/rss+xml; charset=utf-8"), content), - Self::Rdf(content) => (HeaderValue::from_static("application/rdf+xml; charset=utf-8"), content), + Self::Atom(content) => ( + HeaderValue::from_static("application/atom+xml; charset=utf-8"), + content, + ), + Self::Rss(content) => ( + HeaderValue::from_static("application/rss+xml; charset=utf-8"), + content, + ), + Self::Rdf(content) => ( + HeaderValue::from_static("application/rdf+xml; charset=utf-8"), + content, + ), }; res.headers_mut().insert(CONTENT_TYPE, ctype); content @@ -97,9 +121,14 @@ mod tests { let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), "hello"); - assert_eq!(res.headers().get("content-type").unwrap(), "text/plain; charset=utf-8"); + assert_eq!( + res.headers().get("content-type").unwrap(), + "text/plain; charset=utf-8" + ); } #[tokio::test] @@ -110,9 +139,14 @@ mod tests { } let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), "hello"); - assert_eq!(res.headers().get("content-type").unwrap(), "text/plain; charset=utf-8"); + assert_eq!( + res.headers().get("content-type").unwrap(), + "text/plain; charset=utf-8" + ); } #[tokio::test] @@ -124,9 +158,14 @@ mod tests { let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), "hello"); - assert_eq!(res.headers().get("content-type").unwrap(), "text/plain; charset=utf-8"); + assert_eq!( + res.headers().get("content-type").unwrap(), + "text/plain; charset=utf-8" + ); } #[tokio::test] @@ -137,7 +176,9 @@ mod tests { } let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; assert_eq!(res.take_string().await.unwrap(), r#"{"hello": "world"}"#); assert_eq!( res.headers().get("content-type").unwrap(), @@ -153,8 +194,16 @@ mod tests { } let router = Router::new().push(Router::with_path("test").get(test)); - let mut res = TestClient::get("http://127.0.0.1:5800/test").send(router).await; - assert_eq!(res.take_string().await.unwrap(), "hello"); - assert_eq!(res.headers().get("content-type").unwrap(), "text/html; charset=utf-8"); + let mut res = TestClient::get("http://127.0.0.1:5800/test") + .send(router) + .await; + assert_eq!( + res.take_string().await.unwrap(), + "hello" + ); + assert_eq!( + res.headers().get("content-type").unwrap(), + "text/html; charset=utf-8" + ); } } diff --git a/crates/cors/src/allow_credentials.rs b/crates/cors/src/allow_credentials.rs index 53047b999..e72e21fbb 100644 --- a/crates/cors/src/allow_credentials.rs +++ b/crates/cors/src/allow_credentials.rs @@ -13,7 +13,8 @@ use salvo_core::{Depot, Request}; #[must_use] pub struct AllowCredentials(AllowCredentialsInner); -type JudgeFn = Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> bool + Send + Sync + 'static>; +type JudgeFn = + Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> bool + Send + Sync + 'static>; impl AllowCredentials { /// Allow credentials for all requests /// diff --git a/crates/cors/src/allow_headers.rs b/crates/cors/src/allow_headers.rs index 4cf81ab45..38527dbfc 100644 --- a/crates/cors/src/allow_headers.rs +++ b/crates/cors/src/allow_headers.rs @@ -16,7 +16,9 @@ use salvo_core::{Depot, Request}; #[must_use] pub struct AllowHeaders(AllowHeadersInner); -type JudgeFn = Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static>; +type JudgeFn = Arc< + dyn for<'a> Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static, +>; impl AllowHeaders { /// Allow any headers by sending a wildcard (`*`) /// @@ -81,7 +83,10 @@ impl AllowHeaders { AllowHeadersInner::None => return None, AllowHeadersInner::Exact(v) => v.clone(), AllowHeadersInner::Judge(f) => f(origin?, req, depot), - AllowHeadersInner::MirrorRequest => req.headers().get(header::ACCESS_CONTROL_REQUEST_HEADERS)?.clone(), + AllowHeadersInner::MirrorRequest => req + .headers() + .get(header::ACCESS_CONTROL_REQUEST_HEADERS)? + .clone(), }; Some((header::ACCESS_CONTROL_ALLOW_HEADERS, allow_headers)) diff --git a/crates/cors/src/allow_methods.rs b/crates/cors/src/allow_methods.rs index 4e3442d92..54a796ec6 100644 --- a/crates/cors/src/allow_methods.rs +++ b/crates/cors/src/allow_methods.rs @@ -17,7 +17,9 @@ use super::{separated_by_commas, Any, WILDCARD}; #[must_use] pub struct AllowMethods(AllowMethodsInner); -type JudgeFn = Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static>; +type JudgeFn = Arc< + dyn for<'a> Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static, +>; impl AllowMethods { /// Allow any method by sending a wildcard (`*`) /// @@ -93,7 +95,10 @@ impl AllowMethods { AllowMethodsInner::None => return None, AllowMethodsInner::Exact(v) => v.clone(), AllowMethodsInner::Judge(f) => f(origin?, req, depot), - AllowMethodsInner::MirrorRequest => req.headers().get(header::ACCESS_CONTROL_REQUEST_METHOD)?.clone(), + AllowMethodsInner::MirrorRequest => req + .headers() + .get(header::ACCESS_CONTROL_REQUEST_METHOD)? + .clone(), }; Some((header::ACCESS_CONTROL_ALLOW_METHODS, allow_methods)) diff --git a/crates/cors/src/allow_origin.rs b/crates/cors/src/allow_origin.rs index 396c7522a..64038d62a 100644 --- a/crates/cors/src/allow_origin.rs +++ b/crates/cors/src/allow_origin.rs @@ -15,7 +15,8 @@ use super::{Any, WILDCARD}; #[must_use] pub struct AllowOrigin(OriginInner); -type JudgeFn = Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> bool + Send + Sync + 'static>; +type JudgeFn = + Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> bool + Send + Sync + 'static>; impl AllowOrigin { /// Allow any origin by sending a wildcard (`*`) /// diff --git a/crates/cors/src/expose_headers.rs b/crates/cors/src/expose_headers.rs index cfa1a34d5..701eb3a96 100644 --- a/crates/cors/src/expose_headers.rs +++ b/crates/cors/src/expose_headers.rs @@ -17,7 +17,9 @@ use super::{separated_by_commas, Any, WILDCARD}; #[must_use] pub struct ExposeHeaders(ExposeHeadersInner); -type JudgeFn = Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static>; +type JudgeFn = Arc< + dyn for<'a> Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static, +>; impl ExposeHeaders { /// Expose any / all headers by sending a wildcard (`*`) /// diff --git a/crates/cors/src/lib.rs b/crates/cors/src/lib.rs index d5d68dedd..71922e0ef 100644 --- a/crates/cors/src/lib.rs +++ b/crates/cors/src/lib.rs @@ -268,7 +268,13 @@ pub struct CorsHandler(Cors); #[async_trait] impl Handler for CorsHandler { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { let origin = req.headers().get(&header::ORIGIN); let mut headers = HeaderMap::new(); @@ -370,7 +376,9 @@ mod tests { assert!(headers.get(ACCESS_CONTROL_ALLOW_METHODS).is_some()); assert!(headers.get(ACCESS_CONTROL_ALLOW_HEADERS).is_some()); - let res = TestClient::options("https://google.com").send(&service).await; + let res = TestClient::options("https://google.com") + .send(&service) + .await; let headers = res.headers(); assert!( headers.get(ACCESS_CONTROL_ALLOW_METHODS).is_none(), diff --git a/crates/cors/src/max_age.rs b/crates/cors/src/max_age.rs index 8584c8386..4aa90bc24 100644 --- a/crates/cors/src/max_age.rs +++ b/crates/cors/src/max_age.rs @@ -12,7 +12,9 @@ use salvo_core::{Depot, Request}; #[must_use] pub struct MaxAge(MaxAgeInner); -type JudgeFn = Arc Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static>; +type JudgeFn = Arc< + dyn for<'a> Fn(&'a HeaderValue, &'a Request, &'a Depot) -> HeaderValue + Send + Sync + 'static, +>; impl MaxAge { /// Set a static max-age value diff --git a/crates/csrf/src/lib.rs b/crates/csrf/src/lib.rs index 7425cf4d3..7d02d7bf7 100644 --- a/crates/csrf/src/lib.rs +++ b/crates/csrf/src/lib.rs @@ -260,7 +260,13 @@ impl Csrf { #[async_trait] impl Handler for Csrf { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { match self.store.load(req, depot, &self.cipher).await { Some((token, proof)) => { depot.insert(CSRF_TOKEN_KEY, token); @@ -269,7 +275,9 @@ impl Handler for Csrf { if let Some(token) = &self.find_token(req).await { tracing::debug!("csrf token: {token}"); if !self.cipher.verify(token, &proof) { - tracing::debug!("rejecting request due to invalid or expired CSRF token"); + tracing::debug!( + "rejecting request due to invalid or expired CSRF token" + ); res.status_code(StatusCode::FORBIDDEN); ctrl.skip_rest(); return; @@ -357,13 +365,17 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let mut res = TestClient::post("http://127.0.0.1:5801") @@ -385,13 +397,17 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let mut res = TestClient::post("http://127.0.0.1:5801") @@ -405,17 +421,25 @@ mod tests { #[tokio::test] async fn test_validates_token_in_query() { - let csrf = Csrf::new(BcryptCipher::new(), CookieStore::new(), HeaderFinder::new("csrf-token")); + let csrf = Csrf::new( + BcryptCipher::new(), + CookieStore::new(), + HeaderFinder::new("csrf-token"), + ); let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let mut res = TestClient::post("http://127.0.0.1:5801?a=1&b=2") @@ -437,13 +461,17 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let mut res = TestClient::post("http://127.0.0.1:5801?a=1&b=2") @@ -466,13 +494,17 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let mut res = TestClient::post("http://127.0.0.1:5801") @@ -493,13 +525,17 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let mut res = TestClient::post("http://127.0.0.1:5801") .add_header("cookie", cookie.to_string(), true) @@ -520,17 +556,25 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let res = TestClient::post("http://127.0.0.1:5801") .add_header("x-csrf-token", "aGVsbG8=", true) - .add_header("cookie", cookie.to_string().split_once('.').unwrap().0, true) + .add_header( + "cookie", + cookie.to_string().split_once('.').unwrap().0, + true, + ) .send(&service) .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); @@ -546,17 +590,25 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let res = TestClient::post("http://127.0.0.1:5801") .add_header("x-csrf-token", "aGVsbG8", true) - .add_header("cookie", cookie.to_string().split_once('.').unwrap().0, true) + .add_header( + "cookie", + cookie.to_string().split_once('.').unwrap().0, + true, + ) .send(&service) .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); @@ -572,20 +624,30 @@ mod tests { let router = Router::new().hoop(csrf).get(get_index).post(post_index); let service = Service::new(router); - let mut res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let mut res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let csrf_token = res.take_string().await.unwrap(); - let res = TestClient::get("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::get("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::OK); let cookie = res.cookie("salvo.csrf").unwrap(); - let res = TestClient::post("http://127.0.0.1:5801").send(&service).await; + let res = TestClient::post("http://127.0.0.1:5801") + .send(&service) + .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); let res = TestClient::post("http://127.0.0.1:5801") .add_header("x-csrf-token", csrf_token, true) - .add_header("cookie", cookie.to_string().split_once('.').unwrap().0, true) + .add_header( + "cookie", + cookie.to_string().split_once('.').unwrap().0, + true, + ) .send(&service) .await; assert_eq!(res.status_code.unwrap(), StatusCode::FORBIDDEN); diff --git a/crates/flash/src/lib.rs b/crates/flash/src/lib.rs index f44b4e8fe..f6c6d1287 100644 --- a/crates/flash/src/lib.rs +++ b/crates/flash/src/lib.rs @@ -182,7 +182,11 @@ impl Display for FlashLevel { /// `FlashStore` is for stores flash messages. pub trait FlashStore: Debug + Send + Sync + 'static { /// Get the flash messages from the store. - fn load_flash(&self, req: &mut Request, depot: &mut Depot) -> impl Future> + Send; + fn load_flash( + &self, + req: &mut Request, + depot: &mut Depot, + ) -> impl Future> + Send; /// Save the flash messages to the store. fn save_flash( &self, @@ -192,7 +196,8 @@ pub trait FlashStore: Debug + Send + Sync + 'static { flash: Flash, ) -> impl Future + Send; /// Clear the flash store. - fn clear_flash(&self, depot: &mut Depot, res: &mut Response) -> impl Future + Send; + fn clear_flash(&self, depot: &mut Depot, res: &mut Response) + -> impl Future + Send; } /// A trait for `Depot` to get flash messages. @@ -251,7 +256,9 @@ impl FlashHandler { impl fmt::Debug for FlashHandler { #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("FlashHandler").field("store", &self.store).finish() + f.debug_struct("FlashHandler") + .field("store", &self.store) + .finish() } } #[async_trait] @@ -259,7 +266,13 @@ impl Handler for FlashHandler where S: FlashStore, { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { let mut has_incoming = false; if let Some(flash) = self.store.load_flash(req, depot).await { has_incoming = !flash.is_empty(); @@ -272,7 +285,9 @@ where return; } - let mut flash = depot.remove::(OUTGOING_FLASH_KEY).unwrap_or_default(); + let mut flash = depot + .remove::(OUTGOING_FLASH_KEY) + .unwrap_or_default(); if let Some(min_level) = self.minimum_level { flash.0.retain(|msg| msg.level >= min_level); } @@ -322,7 +337,9 @@ mod tests { .push(Router::with_path("set").get(set_flash)); let service = Service::new(router); - let respone = TestClient::get("http://127.0.0.1:5800/set").send(&service).await; + let respone = TestClient::get("http://127.0.0.1:5800/set") + .send(&service) + .await; assert_eq!(respone.status_code, Some(StatusCode::SEE_OTHER)); let cookie = respone.headers().get(SET_COOKIE).unwrap(); @@ -362,7 +379,9 @@ mod tests { .push(Router::with_path("set").get(set_flash)); let service = Service::new(router); - let respone = TestClient::get("http://127.0.0.1:5800/set").send(&service).await; + let respone = TestClient::get("http://127.0.0.1:5800/set") + .send(&service) + .await; assert_eq!(respone.status_code, Some(StatusCode::SEE_OTHER)); let cookie = respone.headers().get(SET_COOKIE).unwrap(); diff --git a/crates/jwt-auth/src/decoder.rs b/crates/jwt-auth/src/decoder.rs index f0b15a9fa..0d86ac682 100644 --- a/crates/jwt-auth/src/decoder.rs +++ b/crates/jwt-auth/src/decoder.rs @@ -49,13 +49,15 @@ impl ConstDecoder { /// If you're using HMAC with a base64 encoded secret, use this. pub fn from_base64_secret(secret: &str) -> Result { - DecodingKey::from_base64_secret(secret).map(|key| Self::with_validation(key, Validation::default())) + DecodingKey::from_base64_secret(secret) + .map(|key| Self::with_validation(key, Validation::default())) } /// If you are loading a public RSA key in a PEM format, use this. /// Only exists if the feature `use_pem` is enabled. pub fn from_rsa_pem(key: &[u8]) -> Result { - DecodingKey::from_rsa_pem(key).map(|key| Self::with_validation(key, Validation::new(Algorithm::RS256))) + DecodingKey::from_rsa_pem(key) + .map(|key| Self::with_validation(key, Validation::new(Algorithm::RS256))) } /// If you have (n, e) RSA public key components as strings, use this. @@ -75,38 +77,51 @@ impl ConstDecoder { /// If you have a ECDSA public key in PEM format, use this. /// Only exists if the feature `use_pem` is enabled. pub fn from_ec_pem(key: &[u8]) -> Result { - DecodingKey::from_ec_pem(key).map(|key| Self::with_validation(key, Validation::new(Algorithm::ES256))) + DecodingKey::from_ec_pem(key) + .map(|key| Self::with_validation(key, Validation::new(Algorithm::ES256))) } /// If you have (x,y) ECDSA key components pub fn from_ec_components(x: &str, y: &str) -> Result { - DecodingKey::from_ec_components(x, y).map(|key| Self::with_validation(key, Validation::new(Algorithm::ES256))) + DecodingKey::from_ec_components(x, y) + .map(|key| Self::with_validation(key, Validation::new(Algorithm::ES256))) } /// If you have a EdDSA public key in PEM format, use this. /// Only exists if the feature `use_pem` is enabled. pub fn from_ed_pem(key: &[u8]) -> Result { - DecodingKey::from_ed_pem(key).map(|key| Self::with_validation(key, Validation::new(Algorithm::EdDSA))) + DecodingKey::from_ed_pem(key) + .map(|key| Self::with_validation(key, Validation::new(Algorithm::EdDSA))) } /// If you know what you're doing and have a RSA DER encoded public key, use this. pub fn from_rsa_der(der: &[u8]) -> Self { - Self::with_validation(DecodingKey::from_rsa_der(der), Validation::new(Algorithm::RS256)) + Self::with_validation( + DecodingKey::from_rsa_der(der), + Validation::new(Algorithm::RS256), + ) } /// If you know what you're doing and have a RSA EC encoded public key, use this. pub fn from_ec_der(der: &[u8]) -> Self { - Self::with_validation(DecodingKey::from_ec_der(der), Validation::new(Algorithm::ES256)) + Self::with_validation( + DecodingKey::from_ec_der(der), + Validation::new(Algorithm::ES256), + ) } /// If you know what you're doing and have a Ed DER encoded public key, use this. pub fn from_ed_der(der: &[u8]) -> Self { - Self::with_validation(DecodingKey::from_ed_der(der), Validation::new(Algorithm::EdDSA)) + Self::with_validation( + DecodingKey::from_ed_der(der), + Validation::new(Algorithm::EdDSA), + ) } /// From x part (base64 encoded) of the JWK encoding pub fn from_ed_components(x: &str) -> Result { - DecodingKey::from_ed_components(x).map(|key| Self::with_validation(key, Validation::new(Algorithm::EdDSA))) + DecodingKey::from_ed_components(x) + .map(|key| Self::with_validation(key, Validation::new(Algorithm::EdDSA))) } } diff --git a/crates/jwt-auth/src/lib.rs b/crates/jwt-auth/src/lib.rs index 312e563ec..0ff8ac8db 100644 --- a/crates/jwt-auth/src/lib.rs +++ b/crates/jwt-auth/src/lib.rs @@ -107,7 +107,9 @@ use std::marker::PhantomData; #[doc(no_inline)] -pub use jsonwebtoken::{decode, errors::Error as JwtError, Algorithm, DecodingKey, TokenData, Validation}; +pub use jsonwebtoken::{ + decode, errors::Error as JwtError, Algorithm, DecodingKey, TokenData, Validation, +}; use serde::de::DeserializeOwned; use thiserror::Error; @@ -319,7 +321,13 @@ where C: DeserializeOwned + Send + Sync + 'static, D: JwtAuthDecoder + Send + Sync + 'static, { - async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) { + async fn handle( + &self, + req: &mut Request, + depot: &mut Depot, + res: &mut Response, + ctrl: &mut FlowCtrl, + ) { let token = self.find_token(req).await; if let Some(token) = token { match self.decoder.decode::(&token, depot).await { @@ -365,8 +373,8 @@ mod tests { } #[tokio::test] async fn test_jwt_auth() { - let auth_handler: JwtAuth = JwtAuth::new(ConstDecoder::from_secret(b"ABCDEF")) - .finders(vec![ + let auth_handler: JwtAuth = + JwtAuth::new(ConstDecoder::from_secret(b"ABCDEF")).finders(vec![ Box::new(HeaderFinder::new()), Box::new(QueryFinder::new("jwt_token")), Box::new(CookieFinder::new("jwt_token")), diff --git a/crates/macros/src/extract.rs b/crates/macros/src/extract.rs index f8a0dbe73..4e11b53b4 100644 --- a/crates/macros/src/extract.rs +++ b/crates/macros/src/extract.rs @@ -4,7 +4,10 @@ use syn::parse::Parse; use syn::parse::ParseStream; use syn::punctuated::Punctuated; use syn::token::Comma; -use syn::{DeriveInput, Error, Expr, ExprLit, ExprPath, Field, Generics, Lit, Meta, MetaNameValue, Token, Type}; +use syn::{ + DeriveInput, Error, Expr, ExprLit, ExprPath, Field, Generics, Lit, Meta, MetaNameValue, Token, + Type, +}; use crate::{ attribute, omit_type_path_lifetimes, salvo_crate, @@ -49,19 +52,27 @@ impl TryFrom<&Field> for FieldInfo { sources.dedup(); aliases.dedup(); - let (serde_rename, serde_flatten) = - if let Some(SerdeValue { rename, flatten, .. }) = serde_util::parse_value(&field.attrs) { - (rename, flatten) - } else { - (None, false) - }; + let (serde_rename, serde_flatten) = if let Some(SerdeValue { + rename, flatten, .. + }) = serde_util::parse_value(&field.attrs) + { + (rename, flatten) + } else { + (None, false) + }; let flatten = flatten.unwrap_or(serde_flatten); if flatten { if !sources.is_empty() { - return Err(Error::new_spanned(ident, "flatten field should not define souces.")); + return Err(Error::new_spanned( + ident, + "flatten field should not define souces.", + )); } if !aliases.is_empty() { - return Err(Error::new_spanned(ident, "flatten field should not define aliases.")); + return Err(Error::new_spanned( + ident, + "flatten field should not define aliases.", + )); } } @@ -192,7 +203,8 @@ impl ExtractibleArgs { for attr in &attrs { if attr.path().is_ident("salvo") { if let Ok(Some(metas)) = attribute::find_nested_list(attr, "extract") { - let nested = metas.parse_args_with(Punctuated::::parse_terminated)?; + let nested = + metas.parse_args_with(Punctuated::::parse_terminated)?; for meta in nested { match meta { Meta::List(meta) => { @@ -202,7 +214,10 @@ impl ExtractibleArgs { } Meta::NameValue(meta) => { if meta.path.is_ident("rename_all") { - rename_all = Some(parse_path_or_lit_str(&meta.value)?.parse::()?); + rename_all = Some( + parse_path_or_lit_str(&meta.value)? + .parse::()?, + ); } } _ => {} @@ -225,7 +240,10 @@ impl ExtractibleArgs { } fn metadata_source(salvo: &Ident, source: &SourceInfo) -> TokenStream { - let from = Ident::new(&RenameRule::PascalCase.apply_to_field(&source.from), Span::call_site()); + let from = Ident::new( + &RenameRule::PascalCase.apply_to_field(&source.from), + Span::call_site(), + ); let parser = if source.parser.to_lowercase() == "multimap" { Ident::new("MultiMap", Span::call_site()) } else { @@ -320,7 +338,10 @@ pub(crate) fn generate(args: DeriveInput) -> Result { } } if nested_metadata.is_some() && field.sources.len() > 1 { - return Err(Error::new_spanned(name, "Only one source can be from request.")); + return Err(Error::new_spanned( + name, + "Only one source can be from request.", + )); } let aliases = field.aliases.iter().map(|alias| { quote! { @@ -368,8 +389,8 @@ pub(crate) fn generate(args: DeriveInput) -> Result { }; let life_param = args.generics.lifetimes().next(); let code = if let Some(life_param) = life_param { - let ex_life_def = - syn::parse_str(&format!("'__macro_gen_ex:{}", life_param.lifetime)).expect("Invalid lifetime."); + let ex_life_def = syn::parse_str(&format!("'__macro_gen_ex:{}", life_param.lifetime)) + .expect("Invalid lifetime."); let mut generics = args.generics.clone(); generics.params.insert(0, ex_life_def); let impl_generics_de = generics.split_for_impl().0; @@ -408,7 +429,9 @@ pub(crate) fn generate(args: DeriveInput) -> Result { fn parse_path_or_lit_str(expr: &Expr) -> syn::Result { match expr { - Expr::Lit(ExprLit { lit: Lit::Str(s), .. }) => Ok(s.value()), + Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) => Ok(s.value()), Expr::Path(ExprPath { path, .. }) => Ok(path.require_ident()?.to_string()), _ => Err(Error::new_spanned(expr, "invalid indent or lit str")), } diff --git a/crates/macros/src/handler.rs b/crates/macros/src/handler.rs index 001780eb7..6c01892e2 100644 --- a/crates/macros/src/handler.rs +++ b/crates/macros/src/handler.rs @@ -52,7 +52,10 @@ pub(crate) fn generate(input: Item) -> syn::Result { } } let Some(hmtd) = hmtd else { - return Err(syn::Error::new_spanned(item_impl.impl_token, "missing handle function")); + return Err(syn::Error::new_spanned( + item_impl.impl_token, + "missing handle function", + )); }; let hfn = handle_fn(&salvo, &hmtd.sig)?; let ty = &item_impl.self_ty; @@ -102,7 +105,10 @@ fn handle_fn(salvo: &Ident, sig: &Signature) -> syn::Result { call_args.push(ident.ident.clone()); let ty = omit_type_path_lifetimes(ty); let idv = pat.pat.to_token_stream().to_string(); - let idv = idv.rsplit_once(' ').map(|(_, v)| v.to_owned()).unwrap_or(idv); + let idv = idv + .rsplit_once(' ') + .map(|(_, v)| v.to_owned()) + .unwrap_or(idv); let id = Ident::new(&idv, Span::call_site()); let idv = idv.trim_start_matches('_'); diff --git a/crates/macros/src/shared.rs b/crates/macros/src/shared.rs index e831ff5cf..cd956e0c7 100644 --- a/crates/macros/src/shared.rs +++ b/crates/macros/src/shared.rs @@ -39,7 +39,12 @@ pub(crate) fn parse_input_type(input: &FnArg) -> InputType { // such as: // `::std::vec::Vec` is `Vec` // `Vec` is `Vec` - let ident = &nty.path.segments.last().expect("path segment should exists").ident; + let ident = &nty + .path + .segments + .last() + .expect("path segment should exists") + .ident; if ident == "Request" { InputType::Request(p) } else if ident == "Response" { diff --git a/crates/oapi-macros/src/bound.rs b/crates/oapi-macros/src/bound.rs index f1346c008..3ec1cc32c 100644 --- a/crates/oapi-macros/src/bound.rs +++ b/crates/oapi-macros/src/bound.rs @@ -23,7 +23,10 @@ pub(crate) fn without_defaults(generics: &syn::Generics) -> syn::Generics { } } -pub(crate) fn with_where_predicates(generics: &syn::Generics, predicates: &[syn::WherePredicate]) -> syn::Generics { +pub(crate) fn with_where_predicates( + generics: &syn::Generics, + predicates: &[syn::WherePredicate], +) -> syn::Generics { let mut generics = generics.clone(); generics .make_where_clause() @@ -199,7 +202,10 @@ pub(crate) fn with_bound( fn visit_macro(&mut self, _mac: &'ast syn::Macro) {} } - let all_type_params = generics.type_params().map(|param| param.ident.clone()).collect(); + let all_type_params = generics + .type_params() + .map(|param| param.ident.clone()) + .collect(); let mut visitor = FindTyParams { all_type_params, @@ -243,6 +249,9 @@ pub(crate) fn with_bound( }); let mut generics = generics.clone(); - generics.make_where_clause().predicates.extend(new_predicates); + generics + .make_where_clause() + .predicates + .extend(new_predicates); generics } diff --git a/crates/oapi-macros/src/component.rs b/crates/oapi-macros/src/component.rs index 5262b6da2..e66a1209e 100644 --- a/crates/oapi-macros/src/component.rs +++ b/crates/oapi-macros/src/component.rs @@ -4,8 +4,8 @@ use syn::spanned::Spanned; use crate::doc_comment::CommentAttributes; use crate::feature::{ - pop_feature, AdditionalProperties, Description, Feature, FeaturesExt, IsInline, Minimum, Nullable, TryToTokensExt, - Validatable, + pop_feature, AdditionalProperties, Description, Feature, FeaturesExt, IsInline, Minimum, + Nullable, TryToTokensExt, Validatable, }; use crate::schema_type::{SchemaFormat, SchemaType, SchemaTypeInner}; use crate::type_tree::{GenericType, TypeTree, ValueType}; @@ -78,14 +78,16 @@ impl<'c> ComponentSchema { deprecated_stream, )? } - Some(GenericType::Vec | GenericType::LinkedList | GenericType::Set) => ComponentSchema::vec_to_tokens( - &mut tokens, - features, - type_tree, - object_name, - description, - deprecated_stream, - )?, + Some(GenericType::Vec | GenericType::LinkedList | GenericType::Set) => { + ComponentSchema::vec_to_tokens( + &mut tokens, + features, + type_tree, + object_name, + description, + deprecated_stream, + )? + } #[cfg(feature = "smallvec")] Some(GenericType::SmallVec) => ComponentSchema::vec_to_tokens( &mut tokens, @@ -97,7 +99,10 @@ impl<'c> ComponentSchema { )?, Some(GenericType::Option) => { // Add nullable feature if not already exists. Option is always nullable - if !features.iter().any(|feature| matches!(feature, Feature::Nullable(_))) { + if !features + .iter() + .any(|feature| matches!(feature, Feature::Nullable(_))) + { features.push(Nullable::new().into()); } @@ -116,7 +121,13 @@ impl<'c> ComponentSchema { })? .to_tokens(&mut tokens); } - Some(GenericType::Cow | GenericType::Box | GenericType::Arc | GenericType::Rc | GenericType::RefCell) => { + Some( + GenericType::Cow + | GenericType::Box + | GenericType::Arc + | GenericType::Rc + | GenericType::RefCell, + ) => { ComponentSchema::new(ComponentSchemaProps { type_tree: type_tree .children @@ -146,12 +157,17 @@ impl<'c> ComponentSchema { } /// Create `.schema_type(...)` override token stream if nullable is true from given [`SchemaTypeInner`]. - fn get_schema_type_override(nullable: Option, schema_type_inner: SchemaTypeInner) -> Option { + fn get_schema_type_override( + nullable: Option, + schema_type_inner: SchemaTypeInner, + ) -> Option { if let Some(nullable) = nullable { let nullable_schema_type = nullable.into_schema_type_token_stream(); let schema_type = if nullable.value() && !nullable_schema_type.is_empty() { let oapi = crate::oapi_crate(); - Some(quote! { #oapi::oapi::schema::SchemaType::from_iter([#schema_type_inner, #nullable_schema_type]) }) + Some( + quote! { #oapi::oapi::schema::SchemaType::from_iter([#schema_type_inner, #nullable_schema_type]) }, + ) } else { None }; @@ -173,7 +189,8 @@ impl<'c> ComponentSchema { let oapi = crate::oapi_crate(); let example = features.pop_by(|feature| matches!(feature, Feature::Example(_))); let additional_properties = pop_feature!(features => Feature::AdditionalProperties(_)); - let nullable: Option = pop_feature!(features => Feature::Nullable(_)).into_inner(); + let nullable: Option = + pop_feature!(features => Feature::Nullable(_)).into_inner(); let default = pop_feature!(features => Feature::Default(_)) .map(|f| f.try_to_token_stream()) .transpose()?; @@ -204,7 +221,8 @@ impl<'c> ComponentSchema { Ok::<_, Diagnostic>(Some(quote! { .additional_properties(#schema_property) })) })?; - let schema_type = ComponentSchema::get_schema_type_override(nullable, SchemaTypeInner::Object); + let schema_type = + ComponentSchema::get_schema_type_override(nullable, SchemaTypeInner::Object); tokens.extend(quote! { #oapi::oapi::Object::new() @@ -234,7 +252,8 @@ impl<'c> ComponentSchema { let xml = features.extract_vec_xml_feature(type_tree); let max_items = pop_feature!(features => Feature::MaxItems(_)); let min_items = pop_feature!(features => Feature::MinItems(_)); - let nullable: Option = pop_feature!(features => Feature::Nullable(_)).into_inner(); + let nullable: Option = + pop_feature!(features => Feature::Nullable(_)).into_inner(); let default = pop_feature!(features => Feature::Default(_)) .map(|f| f.try_to_token_stream()) .transpose()?; @@ -264,7 +283,8 @@ impl<'c> ComponentSchema { }, false => quote! {}, }; - let schema_type = ComponentSchema::get_schema_type_override(nullable, SchemaTypeInner::Array); + let schema_type = + ComponentSchema::get_schema_type_override(nullable, SchemaTypeInner::Array); let schema = quote! { #oapi::oapi::schema::Array::new().items(#component_schema) @@ -277,7 +297,9 @@ impl<'c> ComponentSchema { let type_path = &**type_tree.path.as_ref().expect("path should not be `None`"); let schema_type = SchemaType { path: type_path, - nullable: nullable.map(|nullable| nullable.value()).unwrap_or_default(), + nullable: nullable + .map(|nullable| nullable.value()) + .unwrap_or_default(), }; feature.validate(&schema_type, type_tree) }; @@ -320,8 +342,11 @@ impl<'c> ComponentSchema { deprecated_stream: Option, ) -> DiagResult<()> { let oapi = crate::oapi_crate(); - let nullable_feat: Option = pop_feature!(features => Feature::Nullable(_)).into_inner(); - let nullable = nullable_feat.map(|nullable| nullable.value()).unwrap_or_default(); + let nullable_feat: Option = + pop_feature!(features => Feature::Nullable(_)).into_inner(); + let nullable = nullable_feat + .map(|nullable| nullable.value()) + .unwrap_or_default(); match type_tree.value_type { ValueType::Primitive => { @@ -333,7 +358,10 @@ impl<'c> ComponentSchema { if schema_type.is_unsigned_integer() { // add default minimum feature only when there is no explicit minimum // provided - if !features.iter().any(|feature| matches!(&feature, Feature::Minimum(_))) { + if !features + .iter() + .any(|feature| matches!(&feature, Feature::Minimum(_))) + { features.push(Minimum::new(0f64, type_path.span()).into()); } } @@ -376,8 +404,10 @@ impl<'c> ComponentSchema { if type_tree.is_object() { let oapi = crate::oapi_crate(); - let nullable_schema_type = - ComponentSchema::get_schema_type_override(nullable_feat, SchemaTypeInner::Object); + let nullable_schema_type = ComponentSchema::get_schema_type_override( + nullable_feat, + SchemaTypeInner::Object, + ); tokens.extend(quote! { #oapi::oapi::Object::new() #nullable_schema_type @@ -471,8 +501,10 @@ impl<'c> ComponentSchema { all_of }, ); - let nullable_schema_type = - ComponentSchema::get_schema_type_override(nullable_feat, SchemaTypeInner::Array); + let nullable_schema_type = ComponentSchema::get_schema_type_override( + nullable_feat, + SchemaTypeInner::Array, + ); quote! { #oapi::oapi::schema::Array::new().items(#all_of) #nullable_schema_type diff --git a/crates/oapi-macros/src/doc_comment.rs b/crates/oapi-macros/src/doc_comment.rs index 4adfcc892..a62172ac3 100644 --- a/crates/oapi-macros/src/doc_comment.rs +++ b/crates/oapi-macros/src/doc_comment.rs @@ -12,7 +12,9 @@ impl CommentAttributes { /// Creates new [`CommentAttributes`] instance from [`Attribute`] slice filtering out all /// other attributes which are not `doc` comments pub(crate) fn from_attributes(attributes: &[Attribute]) -> Self { - Self(Self::as_string_vec(attributes.iter().filter(Self::is_doc_attribute))) + Self(Self::as_string_vec( + attributes.iter().filter(Self::is_doc_attribute), + )) } fn is_doc_attribute(attr: &&Attribute) -> bool { @@ -20,7 +22,10 @@ impl CommentAttributes { } fn as_string_vec<'a, I: Iterator>(attrs: I) -> Vec { - attrs.into_iter().filter_map(Self::parse_doc_comment).collect() + attrs + .into_iter() + .filter_map(Self::parse_doc_comment) + .collect() } fn parse_doc_comment(attr: &Attribute) -> Option { diff --git a/crates/oapi-macros/src/endpoint/attr.rs b/crates/oapi-macros/src/endpoint/attr.rs index 35492a5c9..6fcb144f0 100644 --- a/crates/oapi-macros/src/endpoint/attr.rs +++ b/crates/oapi-macros/src/endpoint/attr.rs @@ -4,7 +4,9 @@ use syn::{parenthesized, parse::Parse}; use syn::{Expr, LitStr}; use crate::operation::request_body::RequestBodyAttr; -use crate::{parse_utils, security_requirement::SecurityRequirementsAttr, Array, Parameter, Response, Token}; +use crate::{ + parse_utils, security_requirement::SecurityRequirementsAttr, Array, Parameter, Response, Token, +}; #[derive(Default, Debug)] pub(crate) struct EndpointAttr<'p> { @@ -28,12 +30,16 @@ impl Parse for EndpointAttr<'_> { let mut attr = EndpointAttr::default(); while !input.is_empty() { - let ident = input - .parse::() - .map_err(|error| syn::Error::new(error.span(), format!("{EXPECTED_ATTRIBUTE_MESSAGE}, {error}")))?; + let ident = input.parse::().map_err(|error| { + syn::Error::new( + error.span(), + format!("{EXPECTED_ATTRIBUTE_MESSAGE}, {error}"), + ) + })?; match &*ident.to_string() { "operation_id" => { - attr.operation_id = Some(parse_utils::parse_next(input, || Expr::parse(input))?); + attr.operation_id = + Some(parse_utils::parse_next(input, || Expr::parse(input))?); } "request_body" => { attr.request_body = Some(input.parse::()?); @@ -41,27 +47,36 @@ impl Parse for EndpointAttr<'_> { "responses" => { let responses; parenthesized!(responses in input); - attr.responses = Punctuated::::parse_terminated(&responses) - .map(|punctuated| punctuated.into_iter().collect::>())?; + attr.responses = + Punctuated::::parse_terminated(&responses) + .map(|punctuated| punctuated.into_iter().collect::>())?; } "status_codes" => { let status_codes; parenthesized!(status_codes in input); - attr.status_codes = Punctuated::::parse_terminated(&status_codes) - .map(|punctuated| punctuated.into_iter().collect::>())?; + attr.status_codes = + Punctuated::::parse_terminated(&status_codes) + .map(|punctuated| punctuated.into_iter().collect::>())?; } "parameters" => { let parameters; parenthesized!(parameters in input); - attr.parameters = Punctuated::::parse_terminated(¶meters) - .map(|punctuated| punctuated.into_iter().collect::>())?; + attr.parameters = + Punctuated::::parse_terminated(¶meters) + .map(|punctuated| punctuated.into_iter().collect::>())?; } "tags" => { let tags; parenthesized!(tags in input); attr.tags = Some( - Punctuated::::parse_terminated(&tags) - .map(|punctuated| punctuated.into_iter().map(|t| t.value()).collect::>())?, + Punctuated::::parse_terminated(&tags).map( + |punctuated| { + punctuated + .into_iter() + .map(|t| t.value()) + .collect::>() + }, + )?, ); } "security" => { @@ -69,7 +84,9 @@ impl Parse for EndpointAttr<'_> { parenthesized!(security in input); attr.security = Some(parse_utils::parse_groups(&security)?) } - "description" => attr.description = Some(parse_utils::parse_next_lit_str_or_expr(input)?), + "description" => { + attr.description = Some(parse_utils::parse_next_lit_str_or_expr(input)?) + } "summary" => attr.summary = Some(parse_utils::parse_next_lit_str_or_expr(input)?), _ => { return Err(syn::Error::new(ident.span(), EXPECTED_ATTRIBUTE_MESSAGE)); diff --git a/crates/oapi-macros/src/endpoint/mod.rs b/crates/oapi-macros/src/endpoint/mod.rs index 17f5f0150..a83947a4b 100644 --- a/crates/oapi-macros/src/endpoint/mod.rs +++ b/crates/oapi-macros/src/endpoint/mod.rs @@ -146,7 +146,10 @@ pub(crate) fn generate(mut attr: EndpointAttr, input: Item) -> syn::Result syn::Result syn::Result<(TokenStream, Vec)> { +fn handle_fn( + salvo: &Ident, + oapi: &Ident, + sig: &Signature, +) -> syn::Result<(TokenStream, Vec)> { let name = &sig.ident; let mut extract_ts = Vec::with_capacity(sig.inputs.len()); let mut call_args: Vec = Vec::with_capacity(sig.inputs.len()); @@ -201,7 +208,10 @@ fn handle_fn(salvo: &Ident, oapi: &Ident, sig: &Signature) -> syn::Result<(Token let ty = omit_type_path_lifetimes(ty); let idv = pat.pat.to_token_stream().to_string(); // If id like `mut pdata`, then idv is `pdata`; - let idv = idv.rsplit_once(' ').map(|(_, v)| v.to_owned()).unwrap_or(idv); + let idv = idv + .rsplit_once(' ') + .map(|(_, v)| v.to_owned()) + .unwrap_or(idv); let id = Ident::new(&idv, Span::call_site()); let idv = idv.trim_start_matches('_'); extract_ts.push(quote!{ diff --git a/crates/oapi-macros/src/feature/ext.rs b/crates/oapi-macros/src/feature/ext.rs index 6cd53155e..f5dde4696 100644 --- a/crates/oapi-macros/src/feature/ext.rs +++ b/crates/oapi-macros/src/feature/ext.rs @@ -45,7 +45,9 @@ pub(crate) trait FeaturesExt { impl FeaturesExt for Vec { fn pop_by(&mut self, op: impl FnMut(&Feature) -> bool) -> Option { - self.iter().position(op).map(|index| self.swap_remove(index)) + self.iter() + .position(op) + .map(|index| self.swap_remove(index)) } fn pop_value_type_feature(&mut self) -> Option { @@ -113,23 +115,28 @@ impl FeaturesExt for Option> { } fn pop_value_type_feature(&mut self) -> Option { - self.as_mut().and_then(|features| features.pop_value_type_feature()) + self.as_mut() + .and_then(|features| features.pop_value_type_feature()) } fn pop_parameter_in_feature(&mut self) -> Option { - self.as_mut().and_then(|features| features.pop_parameter_in_feature()) + self.as_mut() + .and_then(|features| features.pop_parameter_in_feature()) } fn pop_style_feature(&mut self) -> Option