Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(volo-http): implement source for Errors #519

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 26 additions & 22 deletions volo-http/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "volo-http"
version = "0.2.14"
version = "0.3.0-rc.1"
edition.workspace = true
homepage.workspace = true
repository.workspace = true
Expand All @@ -15,8 +15,6 @@ keywords = ["async", "rpc", "http"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html



[badges]
maintenance = { status = "actively-developed" }

Expand Down Expand Up @@ -61,28 +59,30 @@ tracing.workspace = true
url.workspace = true

# =====optional=====
multer = { workspace = true, optional = true }

# server optional
matchit = { workspace = true, optional = true }

# protocol optional
# serde and form, query, json
serde = { workspace = true, optional = true }
serde_urlencoded = { workspace = true, optional = true }
sonic-rs = { workspace = true, optional = true }

# cookie support
cookie = { workspace = true, optional = true, features = ["percent-encode"] }
cookie_store = { workspace = true, optional = true }

# multipart optional
multer = { workspace = true, optional = true }

# websocket optional
tungstenite = { workspace = true, optional = true }
tokio-tungstenite = { workspace = true, optional = true }

# tls optional
tokio-rustls = { workspace = true, optional = true }
tokio-native-tls = { workspace = true, optional = true }

# cookie support
cookie = { workspace = true, optional = true, features = ["percent-encode"] }
cookie_store = { workspace = true, optional = true }

# serde and form, query, json
serde = { workspace = true, optional = true }
serde_urlencoded = { workspace = true, optional = true }
sonic-rs = { workspace = true, optional = true }

[dev-dependencies]
async-stream.workspace = true
libc.workspace = true
Expand All @@ -96,11 +96,22 @@ default = []
default_client = ["client", "json"]
default_server = ["server", "query", "form", "json", "multipart"]

full = ["client", "server", "rustls", "cookie", "query", "form", "json", "multipart", "tls", "ws"]
full = [
"client", "server", # core
"query", "form", "json", # serde
"tls", # https
"cookie", "multipart", "ws",
]

client = ["hyper/client", "hyper/http1"] # client core
server = ["hyper/server", "hyper/http1", "dep:matchit"] # server core

__serde = ["dep:serde"] # a private feature for enabling `serde` by `serde_xxx`
query = ["__serde", "dep:serde_urlencoded"]
form = ["__serde", "dep:serde_urlencoded"]
json = ["__serde", "dep:sonic-rs"]

cookie = ["dep:cookie", "dep:cookie_store"]
multipart = ["dep:multer"]
ws = ["dep:tungstenite", "dep:tokio-tungstenite"]

Expand All @@ -110,13 +121,6 @@ rustls = ["__tls", "dep:tokio-rustls", "volo/rustls"]
native-tls = ["__tls", "dep:tokio-native-tls", "volo/native-tls"]
native-tls-vendored = ["native-tls", "volo/native-tls-vendored"]

cookie = ["dep:cookie", "dep:cookie_store"]

__serde = ["dep:serde"] # a private feature for enabling `serde` by `serde_xxx`
query = ["__serde", "dep:serde_urlencoded"]
form = ["__serde", "dep:serde_urlencoded"]
json = ["__serde", "dep:sonic-rs"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
10 changes: 9 additions & 1 deletion volo-http/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,15 @@ impl fmt::Display for BodyConvertError {
}
}

impl Error for BodyConvertError {}
impl Error for BodyConvertError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
#[cfg(feature = "json")]
Self::JsonDeserializeError(e) => Some(e),
_ => None,
}
}
}

impl From<()> for Body {
fn from(_: ()) -> Self {
Expand Down
30 changes: 28 additions & 2 deletions volo-http/src/error/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ impl fmt::Display for ClientError {
}
}

impl Error for ClientError {}
impl Error for ClientError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(self.source.as_ref()?.as_ref())
}
}

/// Error kind of [`ClientError`]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -174,7 +178,7 @@ macro_rules! simple_error {
paste! {
#[doc = $kind " error \"" $msg "\""]
$(#[$attr])*
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub struct $name;

$(#[$attr])*
Expand All @@ -200,3 +204,25 @@ simple_error!(Builder => BadScheme => "bad scheme");
simple_error!(Builder => BadHostName => "bad host name");
simple_error!(Request => Timeout => "request timeout");
simple_error!(LoadBalance => NoAvailableEndpoint => "no available endpoint");

#[cfg(test)]
mod client_error_tests {
use std::error::Error;

use crate::error::client::{
bad_host_name, bad_scheme, no_address, no_available_endpoint, timeout, BadHostName,
BadScheme, NoAddress, NoAvailableEndpoint, Timeout,
};

#[test]
fn types_downcast() {
assert!(no_address().source().unwrap().is::<NoAddress>());
assert!(bad_scheme().source().unwrap().is::<BadScheme>());
assert!(bad_host_name().source().unwrap().is::<BadHostName>());
assert!(timeout().source().unwrap().is::<Timeout>());
assert!(no_available_endpoint()
.source()
.unwrap()
.is::<NoAvailableEndpoint>());
}
}
13 changes: 13 additions & 0 deletions volo-http/src/error/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ impl fmt::Display for ExtractBodyError {
}
}

impl Error for ExtractBodyError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Generic(e) => Some(e),
Self::String(e) => Some(e),
#[cfg(feature = "json")]
Self::Json(e) => Some(e),
#[cfg(feature = "form")]
Self::Form(e) => Some(e),
}
}
}

impl IntoResponse for ExtractBodyError {
fn into_response(self) -> ServerResponse {
let status = match self {
Expand Down
9 changes: 8 additions & 1 deletion volo-http/src/server/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,14 @@ impl fmt::Display for PathParamsRejection {
}
}

impl Error for PathParamsRejection {}
impl Error for PathParamsRejection {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::LengthMismatch => None,
Self::ParseError(e) => Some(e.as_ref()),
}
}
}

impl IntoResponse for PathParamsRejection {
fn into_response(self) -> ServerResponse {
Expand Down
10 changes: 9 additions & 1 deletion volo-http/src/server/route/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ impl fmt::Display for MatcherError {
}
}

impl Error for MatcherError {}
impl Error for MatcherError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::UriConflict(_) => None,
Self::RouterInsertError(e) => Some(e),
Self::RouterMatchError(e) => Some(e),
}
}
}

pub(super) struct StripPrefixLayer;

Expand Down
12 changes: 9 additions & 3 deletions volo-http/src/server/utils/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

use std::{
borrow::Cow,
error::Error,
fmt,
future::Future,
ops::{Deref, DerefMut},
Expand Down Expand Up @@ -467,7 +468,13 @@ impl fmt::Display for WebSocketError {
}
}

impl std::error::Error for WebSocketError {}
impl Error for WebSocketError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Upgrade(e) => Some(e),
}
}
}

/// What to do when a connection upgrade fails.
///
Expand Down Expand Up @@ -498,7 +505,6 @@ impl OnFailedUpgrade for DefaultOnFailedUpgrade {

/// [`Error`]s while extracting [`WebSocketUpgrade`].
///
/// [`Error`]: std::error::Error
/// [`WebSocketUpgrade`]: crate::server::utils::ws::WebSocketUpgrade
#[derive(Debug)]
pub enum WebSocketUpgradeRejectionError {
Expand Down Expand Up @@ -530,7 +536,7 @@ impl WebSocketUpgradeRejectionError {
}
}

impl std::error::Error for WebSocketUpgradeRejectionError {}
impl Error for WebSocketUpgradeRejectionError {}

impl fmt::Display for WebSocketUpgradeRejectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
Loading