diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 653de509..39fa00ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,14 +5,21 @@ on: push: branches: - main - - '[0-9]+.[0-9]+.x' + - "[0-9]+.[0-9]+.x" + schedule: + - cron: "0 2 * * *" + workflow_dispatch: env: CARGO_INCREMENTAL: 0 + CARGO_NET_GIT_FETCH_WITH_CLI: true CARGO_NET_RETRY: 10 CARGO_TERM_COLOR: always + CARGO_PROFILE_TEST_BUILD_OVERRIDE_DEBUG: true RUST_BACKTRACE: 1 RUSTUP_MAX_RETRIES: 10 + RUSTFLAGS: -D warnings + RUSTDOCFLAGS: -D warnings jobs: test: @@ -26,6 +33,9 @@ jobs: - windows-latest runs-on: ${{ matrix.os }} steps: + - if: runner.os == 'Windows' + name: Install NASM for aws-lc-rs on Windows + uses: ilammy/setup-nasm@v1 - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cargo test --workspace --verbose diff --git a/Cargo.toml b/Cargo.toml index c37d2a33..78e9edab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ viz-smol = { version = "0.1.5", path = "viz-smol" } anyhow = "1.0" async-trait = "0.1" -bytes = "1.5" +bytes = "1.6" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" @@ -70,7 +70,7 @@ sync_wrapper = "1.0" thiserror = "1.0" # router -path-tree = "0.7.6" +path-tree = "0.7.7" # session sessions = "0.6" @@ -82,8 +82,8 @@ headers = "0.4" http = "1.1" http-body = "1" http-body-util = "0.1" -hyper = { version = "1.2", features = ["server"] } -hyper-util = { version = "0.1.3", features = ["server-auto", "tokio"] } +hyper = { version = "1.3" } +hyper-util = { version = "0.1.4", features = ["tokio", "server"] } mime = "0.3" mime_guess = "2.0" percent-encoding = "2.3" @@ -92,21 +92,21 @@ hex = "0.4" rust-embed = "8" futures-util = "0.3" -rustls-pemfile = "1.0" -tokio = { version = "1.36", features = ["net"] } +rustls-pemfile = "2.0" +tokio = { version = "1.37", features = ["net"] } tokio-native-tls = "0.3" -tokio-rustls = "0.24" +tokio-rustls = "0.26" tokio-stream = "0.1" tokio-tungstenite = "0.21" tokio-util = "0.7" # OpenTelemetry -opentelemetry = { version = "0.22", default-features = false } -opentelemetry_sdk = { version = "0.22", default-features = false } -opentelemetry-prometheus = { version = "0.15", features = [ +opentelemetry = { version = "0.23", default-features = false } +opentelemetry_sdk = { version = "0.23", default-features = false } +opentelemetry-prometheus = { version = "0.16", features = [ "prometheus-encoding", ] } -opentelemetry-semantic-conventions = { version = "0.14" } +opentelemetry-semantic-conventions = { version = "0.15" } prometheus = "0.13" # Tracing @@ -117,15 +117,15 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] } tower = "0.4" tower-http = "0.5" -# soml -async-channel = "2.2" -async-executor = "1.8" -async-io = "2.2" +# Soml +async-channel = "2.3" +async-executor = "1.11" +async-io = "2.3" async-net = "2.0" smol-hyper = "0.1.1" smol-macros = "0.1" macro_rules_attribute = "0.2" -futures-lite = { version = "2.1.0", default-features = false, features = ["std"] } +futures-lite = { version = "2.3", default-features = false, features = ["std"] } [workspace.metadata.docs.rs] all-features = true @@ -141,18 +141,22 @@ debug = false [workspace.lints.rust] unsafe_code = "forbid" -rust_2018_idioms = "warn" +# rust_2018_idioms = "warn" single_use_lifetimes = "warn" non_ascii_idents = "warn" +non_local_definitions = 'warn' unreachable_pub = "warn" missing_debug_implementations = "warn" missing_docs = "warn" [workspace.lints.clippy] -all = "deny" -pedantic = "deny" -missing_errors_doc = "warn" -needless_pass_by_value = "warn" +all = "warn" # Downgrade deny-by-default lints +pedantic = "warn" +missing_errors_doc = { level = "allow", priority = 1 } module_name_repetitions = { level = "allow", priority = 1 } too_many_lines = { level = "allow", priority = 1 } type_complexity = { level = "allow", priority = 1 } +lint_groups_priority = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/12270 + +[workspace.lints.rustdoc] +private_intra_doc_links = 'allow' diff --git a/examples/htmlx/Cargo.toml b/examples/htmlx/Cargo.toml index a4f31ad2..37445eae 100644 --- a/examples/htmlx/Cargo.toml +++ b/examples/htmlx/Cargo.toml @@ -12,4 +12,4 @@ serde_json.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } handlebars = { version = "5", features = ["dir_source"] } -once_cell = "1.19" +once_cell = "1" diff --git a/examples/limits/Cargo.toml b/examples/limits/Cargo.toml index a9317da1..fde5fdd5 100644 --- a/examples/limits/Cargo.toml +++ b/examples/limits/Cargo.toml @@ -7,5 +7,5 @@ publish = false [dependencies] viz = { workspace = true, features = ["limits", "json", "form", "multipart"] } -serde = { version = "1.0", features = ["derive"] } +serde = { workspace = true, features = ["derive"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } diff --git a/examples/otel/tracing/Cargo.toml b/examples/otel/tracing/Cargo.toml index 61a854e3..2456589c 100644 --- a/examples/otel/tracing/Cargo.toml +++ b/examples/otel/tracing/Cargo.toml @@ -9,5 +9,5 @@ viz = { workspace = true, features = ["otel-tracing"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } opentelemetry.workspace = true -opentelemetry-otlp = { version = "0.15", default-features = false, features = ["trace", "http-proto"] } opentelemetry_sdk = { workspace = true, features = ["trace", "rt-tokio-current-thread"] } +opentelemetry-otlp = { version = "0.16", default-features = false, features = ["trace", "http-proto"] } diff --git a/examples/routing/openapi/Cargo.toml b/examples/routing/openapi/Cargo.toml index c8599a97..43c07a2c 100644 --- a/examples/routing/openapi/Cargo.toml +++ b/examples/routing/openapi/Cargo.toml @@ -13,4 +13,4 @@ serde_json.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } utoipa = "4" -utoipa-swagger-ui = "6" +utoipa-swagger-ui = "7" diff --git a/examples/static-files/include-dir/Cargo.toml b/examples/static-files/include-dir/Cargo.toml index e4e53903..23d4aebc 100644 --- a/examples/static-files/include-dir/Cargo.toml +++ b/examples/static-files/include-dir/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] viz.workspace = true +http-body-util.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } include_dir = "0.7" -http-body-util = "0.1" diff --git a/examples/static-routes/Cargo.toml b/examples/static-routes/Cargo.toml index b8a82479..dfbc0601 100644 --- a/examples/static-routes/Cargo.toml +++ b/examples/static-routes/Cargo.toml @@ -9,4 +9,4 @@ viz.workspace = true hyper.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } -once_cell = "1.19" +once_cell = "1" diff --git a/examples/templates/askama/Cargo.toml b/examples/templates/askama/Cargo.toml index 4ea7bf7b..2cd7ebef 100644 --- a/examples/templates/askama/Cargo.toml +++ b/examples/templates/askama/Cargo.toml @@ -8,4 +8,5 @@ publish = false viz.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } + askama = "0.12" diff --git a/examples/templates/maud/Cargo.toml b/examples/templates/maud/Cargo.toml index 49e22e8e..ff65ad48 100644 --- a/examples/templates/maud/Cargo.toml +++ b/examples/templates/maud/Cargo.toml @@ -8,4 +8,5 @@ publish = false viz.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } + maud = "0.26" diff --git a/examples/templates/minijinja/Cargo.toml b/examples/templates/minijinja/Cargo.toml index 13d13072..d9e1fd7f 100644 --- a/examples/templates/minijinja/Cargo.toml +++ b/examples/templates/minijinja/Cargo.toml @@ -9,5 +9,5 @@ viz.workspace = true serde.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } -minijinja = { version = "1", features = ["loader"] } +minijinja = { version = "2", features = ["loader"] } once_cell = "1.19" diff --git a/examples/templates/tera/Cargo.toml b/examples/templates/tera/Cargo.toml index 0de34112..763bd7c3 100644 --- a/examples/templates/tera/Cargo.toml +++ b/examples/templates/tera/Cargo.toml @@ -9,5 +9,6 @@ viz.workspace = true serde.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } -tera = "1.18" -once_cell = "1.19" + +tera = "1.19" +once_cell = "1" diff --git a/viz-core/Cargo.toml b/viz-core/Cargo.toml index b5a3f78d..a4dd6ed1 100644 --- a/viz-core/Cargo.toml +++ b/viz-core/Cargo.toml @@ -71,7 +71,7 @@ mime.workspace = true rfc7239 = "0.1" # realip cookie = { version = "0.18", features = ["percent-encode"], optional = true } -form-data = { version = "0.5.3", optional = true } +form-data = { version = "0.5.5", optional = true } serde = { workspace = true, features = ["derive"], optional = true } serde_json = { workspace = true, optional = true } serde_urlencoded = { workspace = true, optional = true } diff --git a/viz-core/src/body.rs b/viz-core/src/body.rs index b33cbec5..bbb7b31e 100644 --- a/viz-core/src/body.rs +++ b/viz-core/src/body.rs @@ -12,7 +12,7 @@ use sync_wrapper::SyncWrapper; use crate::{BoxError, Error, HttpBody, Result}; /// A body state. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum BodyState { /// The body is inited. Normal, @@ -41,7 +41,7 @@ pub enum Body { impl Body { /// Creates an empty body. #[must_use] - pub fn empty() -> Self { + pub const fn empty() -> Self { Self::Empty } diff --git a/viz-core/src/handler.rs b/viz-core/src/handler.rs index ba114bc1..d61aeb44 100644 --- a/viz-core/src/handler.rs +++ b/viz-core/src/handler.rs @@ -211,4 +211,4 @@ pub trait HandlerExt: Handler { } } -impl HandlerExt for T where T: Handler {} +impl HandlerExt for T where T: ?Sized + Handler {} diff --git a/viz-core/src/handler/after.rs b/viz-core/src/handler/after.rs index 4b452389..9ba58d55 100644 --- a/viz-core/src/handler/after.rs +++ b/viz-core/src/handler/after.rs @@ -10,7 +10,7 @@ pub struct After { impl After { /// Creates an [`After`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/and_then.rs b/viz-core/src/handler/and_then.rs index 515388dd..e375f433 100644 --- a/viz-core/src/handler/and_then.rs +++ b/viz-core/src/handler/and_then.rs @@ -10,7 +10,7 @@ pub struct AndThen { impl AndThen { /// Creates an [`AndThen`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/around.rs b/viz-core/src/handler/around.rs index 2e401964..bd68282b 100644 --- a/viz-core/src/handler/around.rs +++ b/viz-core/src/handler/around.rs @@ -13,7 +13,7 @@ pub struct Around { impl Around { /// Creates an [`Around`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/before.rs b/viz-core/src/handler/before.rs index 6eeb901b..56e34d32 100644 --- a/viz-core/src/handler/before.rs +++ b/viz-core/src/handler/before.rs @@ -10,7 +10,7 @@ pub struct Before { impl Before { /// Creates a [`Before`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/catch_unwind.rs b/viz-core/src/handler/catch_unwind.rs index 6ef08f3f..e1484d24 100644 --- a/viz-core/src/handler/catch_unwind.rs +++ b/viz-core/src/handler/catch_unwind.rs @@ -10,7 +10,7 @@ pub struct CatchUnwind { impl CatchUnwind { /// Creates an [`CatchUnwind`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/cloneable.rs b/viz-core/src/handler/cloneable.rs index 75351455..7000ad86 100644 --- a/viz-core/src/handler/cloneable.rs +++ b/viz-core/src/handler/cloneable.rs @@ -1,3 +1,5 @@ +#![allow(clippy::redundant_pub_crate)] + use super::Handler; pub(crate) type BoxCloneable = Box>; diff --git a/viz-core/src/handler/map.rs b/viz-core/src/handler/map.rs index bbb8b45c..a3c0d844 100644 --- a/viz-core/src/handler/map.rs +++ b/viz-core/src/handler/map.rs @@ -10,7 +10,7 @@ pub struct Map { impl Map { /// Creates a [`Map`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/map_err.rs b/viz-core/src/handler/map_err.rs index 54ea3f07..0621a621 100644 --- a/viz-core/src/handler/map_err.rs +++ b/viz-core/src/handler/map_err.rs @@ -10,7 +10,7 @@ pub struct MapErr { impl MapErr { /// Creates a [`MapErr`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/map_into_response.rs b/viz-core/src/handler/map_into_response.rs index 1e871dd7..59cdce3f 100644 --- a/viz-core/src/handler/map_into_response.rs +++ b/viz-core/src/handler/map_into_response.rs @@ -7,7 +7,7 @@ pub struct MapInToResponse(pub(crate) H); impl MapInToResponse { /// Creates a [`MapInToResponse`] handler. #[inline] - pub fn new(h: H) -> Self { + pub const fn new(h: H) -> Self { Self(h) } } diff --git a/viz-core/src/handler/or_else.rs b/viz-core/src/handler/or_else.rs index 942d6f76..c7b8756f 100644 --- a/viz-core/src/handler/or_else.rs +++ b/viz-core/src/handler/or_else.rs @@ -10,7 +10,7 @@ pub struct OrElse { impl OrElse { /// Creates an [`OrElse`] handler. #[inline] - pub fn new(h: H, f: F) -> Self { + pub const fn new(h: H, f: F) -> Self { Self { h, f } } } diff --git a/viz-core/src/handler/service.rs b/viz-core/src/handler/service.rs index 23bf038e..4c1bf39a 100644 --- a/viz-core/src/handler/service.rs +++ b/viz-core/src/handler/service.rs @@ -8,7 +8,7 @@ pub struct ServiceHandler(S); impl ServiceHandler { /// Creates a new [`ServiceHandler`]. - pub fn new(s: S) -> Self { + pub const fn new(s: S) -> Self { Self(s) } } diff --git a/viz-core/src/into_response.rs b/viz-core/src/into_response.rs index 59ad07d3..0aff2e22 100644 --- a/viz-core/src/into_response.rs +++ b/viz-core/src/into_response.rs @@ -26,7 +26,7 @@ impl IntoResponse for Response { impl IntoResponse for Error { fn into_response(self) -> Response { match self { - Error::Boxed(error) => { + Self::Boxed(error) => { let body = error.to_string(); Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) @@ -34,7 +34,7 @@ impl IntoResponse for Error { .body(Full::from(body).into()) .unwrap() } - Error::Responder(resp) | Error::Report(_, resp) => resp, + Self::Responder(resp) | Self::Report(_, resp) => resp, } } } @@ -109,10 +109,10 @@ where T: IntoResponse, { fn into_response(self) -> Response { - match self { - Some(r) => r.into_response(), - None => StatusCode::NOT_FOUND.into_response(), - } + self.map_or_else( + || StatusCode::NOT_FOUND.into_response(), + IntoResponse::into_response, + ) } } diff --git a/viz-core/src/middleware/compression.rs b/viz-core/src/middleware/compression.rs index b34a9d03..cf623d70 100644 --- a/viz-core/src/middleware/compression.rs +++ b/viz-core/src/middleware/compression.rs @@ -66,7 +66,7 @@ pub struct Compress { impl Compress { /// Creates a compressed response with the specified algorithm. - pub fn new(inner: T, algo: ContentCoding) -> Self { + pub const fn new(inner: T, algo: ContentCoding) -> Self { Self { inner, algo } } } @@ -100,7 +100,7 @@ impl IntoResponse for Compress { /// [`ContentCoding`] /// /// [`ContentCoding`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum ContentCoding { /// gzip Gzip, @@ -117,13 +117,13 @@ impl FromStr for ContentCoding { fn from_str(s: &str) -> Result { if s.eq_ignore_ascii_case("deflate") { - Ok(ContentCoding::Deflate) + Ok(Self::Deflate) } else if s.eq_ignore_ascii_case("gzip") { - Ok(ContentCoding::Gzip) + Ok(Self::Gzip) } else if s.eq_ignore_ascii_case("br") { - Ok(ContentCoding::Brotli) + Ok(Self::Brotli) } else if s == "*" { - Ok(ContentCoding::Any) + Ok(Self::Any) } else { Err(()) } diff --git a/viz-core/src/middleware/cors.rs b/viz-core/src/middleware/cors.rs index 8c14bed5..2bc22953 100644 --- a/viz-core/src/middleware/cors.rs +++ b/viz-core/src/middleware/cors.rs @@ -37,7 +37,7 @@ impl Config { /// /// [MDN]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age #[must_use] - pub fn max_age(mut self, max_age: usize) -> Self { + pub const fn max_age(mut self, max_age: usize) -> Self { self.max_age = max_age; self } @@ -46,7 +46,7 @@ impl Config { /// /// [MDN]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials #[must_use] - pub fn credentials(mut self, credentials: bool) -> Self { + pub const fn credentials(mut self, credentials: bool) -> Self { self.credentials = credentials; self } diff --git a/viz-core/src/middleware/csrf.rs b/viz-core/src/middleware/csrf.rs index fff98200..8a7aff2f 100644 --- a/viz-core/src/middleware/csrf.rs +++ b/viz-core/src/middleware/csrf.rs @@ -86,23 +86,24 @@ where pub fn get(&self, req: &Request) -> Result>> { let inner = self.as_ref(); match inner.store { - Store::Cookie => { - match self - .get_cookie(&req.cookies()?) - .map(|c| c.value().to_string()) - { - None => Ok(None), - Some(raw_token) => base64::engine::general_purpose::URL_SAFE_NO_PAD - .decode(raw_token) - .ok() - .filter(|b| b.len() == 64) - .map(unmask::<32>) - .map(Option::Some) - .ok_or_else(|| { - (StatusCode::INTERNAL_SERVER_ERROR, "Invalid csrf token").into_error() - }), - } - } + Store::Cookie => self + .get_cookie(&req.cookies()?) + .map(|c| c.value().to_string()) + .map_or_else( + || Ok(None), + |raw_token| { + base64::engine::general_purpose::URL_SAFE_NO_PAD + .decode(raw_token) + .ok() + .filter(|b| b.len() == 64) + .map(unmask::<32>) + .map(Option::Some) + .ok_or_else(|| { + (StatusCode::INTERNAL_SERVER_ERROR, "Invalid csrf token") + .into_error() + }) + }, + ), #[cfg(feature = "session")] Store::Session => req.session().get(inner.cookie_options.name), } @@ -261,6 +262,7 @@ pub fn verify(secret: &[u8], raw_token: String) -> bool { } /// Retures masked token +#[allow(clippy::needless_collect)] fn mask(secret: &[u8], mut otp: Vec) -> Vec { otp.extend::>( secret diff --git a/viz-core/src/middleware/helper.rs b/viz-core/src/middleware/helper.rs index b03af4d7..2099a4c4 100644 --- a/viz-core/src/middleware/helper.rs +++ b/viz-core/src/middleware/helper.rs @@ -35,7 +35,7 @@ impl CookieOptions { /// Creates new `CookieOptions` with `name` #[must_use] - pub fn name(mut self, name: &'static str) -> Self { + pub const fn name(mut self, name: &'static str) -> Self { self.name = name; self } @@ -56,21 +56,21 @@ impl CookieOptions { /// Creates new `CookieOptions` with `path` #[must_use] - pub fn path(mut self, path: &'static str) -> Self { + pub const fn path(mut self, path: &'static str) -> Self { self.path = path; self } /// Creates new `CookieOptions` with `secure` #[must_use] - pub fn secure(mut self, secure: bool) -> Self { + pub const fn secure(mut self, secure: bool) -> Self { self.secure = secure; self } /// Creates new `CookieOptions` with `http_only` #[must_use] - pub fn http_only(mut self, http_only: bool) -> Self { + pub const fn http_only(mut self, http_only: bool) -> Self { self.http_only = http_only; self } diff --git a/viz-core/src/middleware/otel/metrics.rs b/viz-core/src/middleware/otel/metrics.rs index 519ed2bc..4837d05e 100644 --- a/viz-core/src/middleware/otel/metrics.rs +++ b/viz-core/src/middleware/otel/metrics.rs @@ -2,7 +2,7 @@ //! //! [`OpenTelemetry`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md -use std::{net::SocketAddr, time::SystemTime}; +use std::time::SystemTime; use http::uri::Scheme; use opentelemetry::{ @@ -10,8 +10,8 @@ use opentelemetry::{ KeyValue, }; use opentelemetry_semantic_conventions::trace::{ - CLIENT_ADDRESS, CLIENT_SOCKET_ADDRESS, HTTP_REQUEST_METHOD, HTTP_RESPONSE_STATUS_CODE, - HTTP_ROUTE, NETWORK_PROTOCOL_VERSION, SERVER_ADDRESS, SERVER_PORT, URL_SCHEME, + CLIENT_ADDRESS, HTTP_REQUEST_METHOD, HTTP_RESPONSE_STATUS_CODE, HTTP_ROUTE, + NETWORK_PROTOCOL_VERSION, SERVER_ADDRESS, SERVER_PORT, URL_SCHEME, }; use crate::{Handler, IntoResponse, Request, RequestExt, Response, ResponseExt, Result, Transform}; @@ -60,7 +60,7 @@ impl Config { .with_unit(Unit::new("By")) .init(); - Config { + Self { active_requests, duration, request_size, @@ -155,17 +155,9 @@ fn build_attributes(req: &Request, http_route: &str) -> Vec { format!("{:?}", req.version()), )); - let remote_addr = req.remote_addr(); - if let Some(remote_addr) = remote_addr { + if let Some(remote_addr) = req.remote_addr() { attributes.push(KeyValue::new(CLIENT_ADDRESS, remote_addr.to_string())); } - if let Some(realip) = req.realip().map(|value| value.0).filter(|realip| { - remote_addr - .map(SocketAddr::ip) - .map_or(true, |remoteip| &remoteip != realip) - }) { - attributes.push(KeyValue::new(CLIENT_SOCKET_ADDRESS, realip.to_string())); - } let uri = req.uri(); if let Some(host) = uri.host() { diff --git a/viz-core/src/middleware/otel/tracing.rs b/viz-core/src/middleware/otel/tracing.rs index 72058516..2d9b36a7 100644 --- a/viz-core/src/middleware/otel/tracing.rs +++ b/viz-core/src/middleware/otel/tracing.rs @@ -2,7 +2,7 @@ //! //! [`OpenTelemetry`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md -use std::{net::SocketAddr, sync::Arc}; +use std::sync::Arc; use http::{uri::Scheme, HeaderValue}; use opentelemetry::{ @@ -12,10 +12,9 @@ use opentelemetry::{ Context, KeyValue, }; use opentelemetry_semantic_conventions::trace::{ - CLIENT_ADDRESS, CLIENT_SOCKET_ADDRESS, EXCEPTION_MESSAGE, HTTP_REQUEST_BODY_SIZE, - HTTP_REQUEST_METHOD, HTTP_RESPONSE_BODY_SIZE, HTTP_RESPONSE_STATUS_CODE, HTTP_ROUTE, - NETWORK_PROTOCOL_VERSION, SERVER_ADDRESS, SERVER_PORT, URL_PATH, URL_QUERY, URL_SCHEME, - USER_AGENT_ORIGINAL, + CLIENT_ADDRESS, EXCEPTION_MESSAGE, HTTP_REQUEST_BODY_SIZE, HTTP_REQUEST_METHOD, + HTTP_RESPONSE_BODY_SIZE, HTTP_RESPONSE_STATUS_CODE, HTTP_ROUTE, NETWORK_PROTOCOL_VERSION, + SERVER_ADDRESS, SERVER_PORT, URL_PATH, URL_QUERY, URL_SCHEME, USER_AGENT_ORIGINAL, }; use crate::{ @@ -136,7 +135,7 @@ struct RequestHeaderCarrier<'a> { } impl<'a> RequestHeaderCarrier<'a> { - fn new(headers: &'a HeaderMap) -> Self { + const fn new(headers: &'a HeaderMap) -> Self { RequestHeaderCarrier { headers } } } @@ -166,17 +165,9 @@ fn build_attributes(req: &Request, http_route: &str) -> Vec { format!("{:?}", req.version()), )); - let remote_addr = req.remote_addr(); - if let Some(remote_addr) = remote_addr { + if let Some(remote_addr) = req.remote_addr() { attributes.push(KeyValue::new(CLIENT_ADDRESS, remote_addr.to_string())); } - if let Some(realip) = req.realip().map(|value| value.0).filter(|realip| { - remote_addr - .map(SocketAddr::ip) - .map_or(true, |remoteip| &remoteip != realip) - }) { - attributes.push(KeyValue::new(CLIENT_SOCKET_ADDRESS, realip.to_string())); - } let uri = req.uri(); if let Some(host) = uri.host() { diff --git a/viz-core/src/middleware/session/config.rs b/viz-core/src/middleware/session/config.rs index 8b83b8ec..44083454 100644 --- a/viz-core/src/middleware/session/config.rs +++ b/viz-core/src/middleware/session/config.rs @@ -149,6 +149,6 @@ where } } -fn max_age() -> Duration { +const fn max_age() -> Duration { Duration::from_secs(CookieOptions::MAX_AGE) } diff --git a/viz-core/src/response.rs b/viz-core/src/response.rs index 780f7319..5545b050 100644 --- a/viz-core/src/response.rs +++ b/viz-core/src/response.rs @@ -223,14 +223,17 @@ impl ResponseExt for Response { where T: AsRef + Send, { - let value = if let Some(filename) = name { - filename - } else if let Some(filename) = path.as_ref().file_name().and_then(std::ffi::OsStr::to_str) { - filename - } else { - "download" - } - .escape_default(); + let value = name + .map_or_else( + || { + path.as_ref() + .file_name() + .and_then(std::ffi::OsStr::to_str) + .map_or("download", |filename| filename) + }, + |filename| filename, + ) + .escape_default(); let mut resp = Self::attachment(&format!("attachment; filename=\"{value}\"")); *resp.body_mut() = Body::from_stream(tokio_util::io::ReaderStream::new( diff --git a/viz-core/src/types/cookie.rs b/viz-core/src/types/cookie.rs index 0d5d3132..4a884493 100644 --- a/viz-core/src/types/cookie.rs +++ b/viz-core/src/types/cookie.rs @@ -226,7 +226,7 @@ pub enum CookiesError { impl From for Error { fn from(e: CookiesError) -> Self { - Error::Responder(e.into_response()) + Self::Responder(e.into_response()) } } diff --git a/viz-core/src/types/form.rs b/viz-core/src/types/form.rs index 6a7b0b79..0d8e2b16 100644 --- a/viz-core/src/types/form.rs +++ b/viz-core/src/types/form.rs @@ -17,8 +17,8 @@ pub struct Form(pub T); impl Form { /// Create new `Form` instance. #[inline] - pub fn new(data: T) -> Self { - Form(data) + pub const fn new(data: T) -> Self { + Self(data) } /// Consumes the Form, returning the wrapped value. @@ -33,7 +33,7 @@ where T: Clone, { fn clone(&self) -> Self { - Form(self.0.clone()) + Self(self.0.clone()) } } diff --git a/viz-core/src/types/header.rs b/viz-core/src/types/header.rs index bcbd63b1..9df63ba9 100644 --- a/viz-core/src/types/header.rs +++ b/viz-core/src/types/header.rs @@ -16,7 +16,7 @@ pub struct Header(pub T); impl Header { /// Create new `Header` instance. #[inline] - pub fn new(t: T) -> Self { + pub const fn new(t: T) -> Self { Self(t) } diff --git a/viz-core/src/types/json.rs b/viz-core/src/types/json.rs index 04c3fc47..196afce7 100644 --- a/viz-core/src/types/json.rs +++ b/viz-core/src/types/json.rs @@ -15,8 +15,8 @@ pub struct Json(pub T); impl Json { /// Create new `Json` instance. #[inline] - pub fn new(data: T) -> Self { - Json(data) + pub const fn new(data: T) -> Self { + Self(data) } /// Consumes the JSON, returning the wrapped value. @@ -31,7 +31,7 @@ where T: Clone, { fn clone(&self) -> Self { - Json(self.0.clone()) + Self(self.0.clone()) } } diff --git a/viz-core/src/types/limits.rs b/viz-core/src/types/limits.rs index 7da0d6ef..bc8da4e2 100644 --- a/viz-core/src/types/limits.rs +++ b/viz-core/src/types/limits.rs @@ -19,10 +19,10 @@ pub struct Limits { impl Default for Limits { fn default() -> Self { - let limits = Limits::new() - .set("bytes", Limits::NORMAL) - .set("payload", Limits::NORMAL) - .set("text", Limits::NORMAL); + let limits = Self::new() + .set("bytes", Self::NORMAL) + .set("payload", Self::NORMAL) + .set("text", Self::NORMAL); #[cfg(feature = "json")] let limits = limits.set(::NAME, ::LIMIT); @@ -41,7 +41,7 @@ impl Limits { /// Creates a new Limits. #[must_use] pub fn new() -> Self { - Limits { + Self { inner: Arc::new(Vec::new()), } } diff --git a/viz-core/src/types/multipart.rs b/viz-core/src/types/multipart.rs index 6b5155be..5693a186 100644 --- a/viz-core/src/types/multipart.rs +++ b/viz-core/src/types/multipart.rs @@ -39,18 +39,18 @@ impl IntoResponse for MultipartError { fn into_response(self) -> Response { ( match self { - MultipartError::InvalidHeader - | MultipartError::InvalidContentDisposition - | MultipartError::FileTooLarge(_) - | MultipartError::FieldTooLarge(_) - | MultipartError::PartsTooMany(_) - | MultipartError::FieldsTooMany(_) - | MultipartError::FilesTooMany(_) - | MultipartError::FieldNameTooLong(_) => StatusCode::BAD_REQUEST, - MultipartError::PayloadTooLarge(_) => StatusCode::PAYLOAD_TOO_LARGE, - MultipartError::Stream(_) - | MultipartError::BoxError(_) - | MultipartError::TryLockError(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::InvalidHeader + | Self::InvalidContentDisposition + | Self::FileTooLarge(_) + | Self::FieldTooLarge(_) + | Self::PartsTooMany(_) + | Self::FieldsTooMany(_) + | Self::FilesTooMany(_) + | Self::FieldNameTooLong(_) => StatusCode::BAD_REQUEST, + Self::PayloadTooLarge(_) => StatusCode::PAYLOAD_TOO_LARGE, + Self::Stream(_) | Self::BoxError(_) | Self::TryLockError(_) => { + StatusCode::INTERNAL_SERVER_ERROR + } }, self.to_string(), ) diff --git a/viz-core/src/types/params.rs b/viz-core/src/types/params.rs index 615e34f2..0357c63f 100644 --- a/viz-core/src/types/params.rs +++ b/viz-core/src/types/params.rs @@ -14,6 +14,7 @@ use crate::{ Error, FromRequest, IntoResponse, Request, RequestExt, Response, StatusCode, ThisError, }; +#[allow(clippy::redundant_pub_crate)] pub(crate) use de::PathDeserializer; /// Extracts params from the path of a URL. diff --git a/viz-core/src/types/params/de.rs b/viz-core/src/types/params/de.rs index da262419..a8a2d257 100644 --- a/viz-core/src/types/params/de.rs +++ b/viz-core/src/types/params/de.rs @@ -40,13 +40,14 @@ macro_rules! parse_single_value { }; } +#[allow(clippy::redundant_pub_crate)] pub(crate) struct PathDeserializer<'de> { path: &'de [(String, String)], } impl<'de> PathDeserializer<'de> { #[inline] - pub(crate) fn new(path: &'de [(String, String)]) -> Self { + pub(crate) const fn new(path: &'de [(String, String)]) -> Self { Self { path } } } diff --git a/viz-core/src/types/payload.rs b/viz-core/src/types/payload.rs index f99f84bd..3398220e 100644 --- a/viz-core/src/types/payload.rs +++ b/viz-core/src/types/payload.rs @@ -60,20 +60,20 @@ impl IntoResponse for PayloadError { fn into_response(self) -> Response { ( match self { - PayloadError::Empty - | PayloadError::Read - | PayloadError::Parse - | PayloadError::MissingBoundary - | PayloadError::Utf8(_) - | PayloadError::Hyper(_) => StatusCode::BAD_REQUEST, + Self::Empty + | Self::Read + | Self::Parse + | Self::MissingBoundary + | Self::Utf8(_) + | Self::Hyper(_) => StatusCode::BAD_REQUEST, #[cfg(feature = "json")] - PayloadError::Json(_) => StatusCode::BAD_REQUEST, + Self::Json(_) => StatusCode::BAD_REQUEST, #[cfg(any(feature = "form", feature = "query"))] - PayloadError::UrlDecode(_) => StatusCode::BAD_REQUEST, - PayloadError::LengthRequired => StatusCode::LENGTH_REQUIRED, - PayloadError::TooLarge => StatusCode::PAYLOAD_TOO_LARGE, - PayloadError::UnsupportedMediaType(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE, - PayloadError::Used => StatusCode::INTERNAL_SERVER_ERROR, + Self::UrlDecode(_) => StatusCode::BAD_REQUEST, + Self::LengthRequired => StatusCode::LENGTH_REQUIRED, + Self::TooLarge => StatusCode::PAYLOAD_TOO_LARGE, + Self::UnsupportedMediaType(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE, + Self::Used => StatusCode::INTERNAL_SERVER_ERROR, }, self.to_string(), ) @@ -126,12 +126,14 @@ pub trait Payload { /// Will return [`PayloadError::TooLarge`] if the detected content length is too large. #[inline] fn check_length(len: Option, limit: Option) -> Result<(), PayloadError> { - match len { - None => Err(PayloadError::LengthRequired), - Some(len) => (len <= Self::limit(limit)) - .then_some(()) - .ok_or_else(|| PayloadError::TooLarge), - } + len.map_or_else( + || Err(PayloadError::LengthRequired), + |len| { + (len <= Self::limit(limit)) + .then_some(()) + .ok_or_else(|| PayloadError::TooLarge) + }, + ) } /// Checks `Content-Type` & `Content-Length` diff --git a/viz-core/src/types/query.rs b/viz-core/src/types/query.rs index fe1c756e..4c121dd0 100644 --- a/viz-core/src/types/query.rs +++ b/viz-core/src/types/query.rs @@ -15,8 +15,8 @@ pub struct Query(pub T); impl Query { /// Create new `Query` instance. #[inline] - pub fn new(data: T) -> Self { - Query(data) + pub const fn new(data: T) -> Self { + Self(data) } /// Consumes the Query, returning the wrapped value. @@ -31,7 +31,7 @@ where T: Clone, { fn clone(&self) -> Self { - Query(self.0.clone()) + Self(self.0.clone()) } } diff --git a/viz-core/src/types/session.rs b/viz-core/src/types/session.rs index fbef5a31..f33dd7a1 100644 --- a/viz-core/src/types/session.rs +++ b/viz-core/src/types/session.rs @@ -54,17 +54,15 @@ impl Session { where T: DeserializeOwned, { - let read = self - .lock_data() + self.lock_data() .read() - .map_err(|e| responder_error((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())))?; - - let val = read.get(key).cloned(); - - match val { - Some(t) => from_value(t).map(Some).map_err(report_error), - None => Ok(None), - } + .map_err(|e| responder_error((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())))? + .get(key) + .cloned() + .map_or_else( + || Ok(None), + |t| from_value(t).map(Some).map_err(report_error), + ) } /// Sets a value by the key diff --git a/viz-core/src/types/sse.rs b/viz-core/src/types/sse.rs index 29a1672e..3a2e40ff 100644 --- a/viz-core/src/types/sse.rs +++ b/viz-core/src/types/sse.rs @@ -29,7 +29,7 @@ where { /// Creates a new Server-Sent Event. #[must_use] - pub fn new(stream: S) -> Self { + pub const fn new(stream: S) -> Self { Self { stream, interval: None, diff --git a/viz-core/src/types/sse/event.rs b/viz-core/src/types/sse/event.rs index da9f2890..d41503d8 100644 --- a/viz-core/src/types/sse/event.rs +++ b/viz-core/src/types/sse/event.rs @@ -86,6 +86,6 @@ impl fmt::Display for Event { impl From for Bytes { fn from(e: Event) -> Self { - Bytes::from(e.to_string()) + Self::from(e.to_string()) } } diff --git a/viz-core/src/types/state.rs b/viz-core/src/types/state.rs index 396bf44f..6345e458 100644 --- a/viz-core/src/types/state.rs +++ b/viz-core/src/types/state.rs @@ -18,7 +18,7 @@ impl State { /// Create new `State` instance. #[must_use] #[inline] - pub fn new(data: T) -> Self { + pub const fn new(data: T) -> Self { Self(data) } @@ -96,7 +96,7 @@ impl StateError { /// Creates a `State` Error #[must_use] pub fn new() -> Self { - StateError(type_name::()) + Self(type_name::()) } } diff --git a/viz-core/src/types/websocket.rs b/viz-core/src/types/websocket.rs index ee8c37de..24ffa8cf 100644 --- a/viz-core/src/types/websocket.rs +++ b/viz-core/src/types/websocket.rs @@ -118,7 +118,7 @@ impl FromRequest for WebSocket { .get(UPGRADE) .ok_or(WebSocketError::MissingUpgrade) .and_then(|h| { - if h.as_bytes().eq_ignore_ascii_case(WebSocket::NAME) { + if h.as_bytes().eq_ignore_ascii_case(Self::NAME) { Ok(()) } else { Err(WebSocketError::InvalidUpgrade) diff --git a/viz-core/src/types/websocket/error.rs b/viz-core/src/types/websocket/error.rs index 2b5a6d0f..8404e6e6 100644 --- a/viz-core/src/types/websocket/error.rs +++ b/viz-core/src/types/websocket/error.rs @@ -44,15 +44,15 @@ impl IntoResponse for WebSocketError { fn into_response(self) -> Response { ( match self { - WebSocketError::MissingConnectUpgrade - | WebSocketError::InvalidConnectUpgrade - | WebSocketError::MissingUpgrade - | WebSocketError::InvalidUpgrade - | WebSocketError::MissingWebSocketVersion - | WebSocketError::InvalidWebSocketVersion - | WebSocketError::MissingWebSocketKey => StatusCode::BAD_REQUEST, - WebSocketError::ConnectionNotUpgradable => StatusCode::UPGRADE_REQUIRED, - WebSocketError::TungsteniteError(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::MissingConnectUpgrade + | Self::InvalidConnectUpgrade + | Self::MissingUpgrade + | Self::InvalidUpgrade + | Self::MissingWebSocketVersion + | Self::InvalidWebSocketVersion + | Self::MissingWebSocketKey => StatusCode::BAD_REQUEST, + Self::ConnectionNotUpgradable => StatusCode::UPGRADE_REQUIRED, + Self::TungsteniteError(_) => StatusCode::INTERNAL_SERVER_ERROR, }, self.to_string(), ) diff --git a/viz-core/tests/handler.rs b/viz-core/tests/handler.rs index ff776b40..dd503923 100644 --- a/viz-core/tests/handler.rs +++ b/viz-core/tests/handler.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +#![allow(non_local_definitions)] #![allow(clippy::unused_async)] #![allow(clippy::similar_names)] #![allow(clippy::wildcard_imports)] @@ -26,7 +27,7 @@ async fn handler() -> Result<()> { type Error = std::convert::Infallible; async fn extract(_: &mut Request) -> Result { - Ok(MyU8(u8::MAX)) + Ok(Self(u8::MAX)) } } @@ -36,13 +37,13 @@ async fn handler() -> Result<()> { type Error = std::convert::Infallible; async fn extract(req: &mut Request) -> Result { - Ok(MyString(req.uri().path().to_string())) + Ok(Self(req.uri().path().to_string())) } } impl From for Error { fn from(e: MyString) -> Self { - Error::Responder(Response::new(Full::from(e.0).into())) + Self::Responder(Response::new(Full::from(e.0).into())) } } @@ -55,7 +56,7 @@ async fn handler() -> Result<()> { impl From for Error { fn from(e: CustomError) -> Self { - Error::Responder(e.into_response()) + Self::Responder(e.into_response()) } } @@ -83,7 +84,7 @@ async fn handler() -> Result<()> { impl From for Error { fn from(e: CustomError2) -> Self { // Error::Responder(e.into_response()) - Error::Report(Box::new(e), CustomError::NotFound.into_response()) + Self::Report(Box::new(e), CustomError::NotFound.into_response()) } } @@ -198,11 +199,11 @@ async fn handler() -> Result<()> { } } - fn map(res: Response) -> Response { + const fn map(res: Response) -> Response { res } - fn map_err(err: Error) -> Error { + const fn map_err(err: Error) -> Error { err } @@ -313,6 +314,7 @@ async fn handler() -> Result<()> { brha, brhb, brhc, brhd, brhe, brhf, brhg, brhh, brhi, brhj, brhk, brhl, brhm, ]; + #[allow(clippy::redundant_clone)] let y = v.clone(); assert!(!y.is_empty()); diff --git a/viz-handlers/src/embed.rs b/viz-handlers/src/embed.rs index 1ea13e71..d7c3156e 100644 --- a/viz-handlers/src/embed.rs +++ b/viz-handlers/src/embed.rs @@ -64,10 +64,11 @@ where async fn call(&self, req: Request) -> Self::Output { serve::( - match req.route_info().params.first().map(|(_, v)| v) { - Some(p) => p, - None => "index.html", - }, + req.route_info() + .params + .first() + .map(|(_, v)| v) + .map_or("index.html", |p| p), &req, ) } diff --git a/viz-handlers/src/prometheus.rs b/viz-handlers/src/prometheus.rs index 53dfd7d3..44b78ef9 100644 --- a/viz-handlers/src/prometheus.rs +++ b/viz-handlers/src/prometheus.rs @@ -25,7 +25,7 @@ pub struct Prometheus { impl Prometheus { /// Creates a new [`Prometheus`]. #[must_use] - pub fn new(registry: Registry) -> Self { + pub const fn new(registry: Registry) -> Self { Self { registry } } } diff --git a/viz-handlers/src/serve.rs b/viz-handlers/src/serve.rs index bbf19671..39a70ca3 100644 --- a/viz-handlers/src/serve.rs +++ b/viz-handlers/src/serve.rs @@ -84,7 +84,7 @@ impl Dir { /// Enable directory listing, `disabled` by default. #[must_use] - pub fn listing(mut self) -> Self { + pub const fn listing(mut self) -> Self { self.listing = true; self } diff --git a/viz-handlers/src/serve/directory.rs b/viz-handlers/src/serve/directory.rs index 900f2f3c..aa5693b0 100644 --- a/viz-handlers/src/serve/directory.rs +++ b/viz-handlers/src/serve/directory.rs @@ -13,19 +13,19 @@ use std::{ use viz_core::{IntoResponse, Response, ResponseExt}; #[derive(Debug)] -pub(crate) struct Directory { +pub(super) struct Directory { name: String, paths: Paths, files: Files, } impl Directory { - pub(crate) fn new( + pub(super) fn new( base: &str, prev: bool, root: &Path, unlisted: &Option>, - ) -> Option { + ) -> Option { let mut entries = read_dir(root).ok()?; let mut files = Vec::new(); @@ -88,7 +88,7 @@ impl Directory { paths.reverse(); - Some(Directory { + Some(Self { name: base.to_string(), paths: Paths(paths), files: Files(files), @@ -116,7 +116,7 @@ impl Display for Directory { /// Path: (url, name) #[derive(Debug)] -pub(crate) struct Paths(Vec<(String, String)>); +struct Paths(Vec<(String, String)>); impl Display for Paths { fn fmt(&self, f: &mut Formatter<'_>) -> Result { @@ -129,11 +129,11 @@ impl Display for Paths { /// File: (relative, title, kind, ext, base) #[derive(Debug)] -pub(crate) struct Files(Vec<(String, String, bool, Option, String)>); +struct Files(Vec<(String, String, bool, Option, String)>); impl Display for Files { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - #[allow(clippy::manual_unwrap_or_default)] + #[allow(clippy::unwrap_or_default)] for (relative, title, kind, ext, base) in &self.0 { writeln!( f, @@ -141,10 +141,7 @@ impl Display for Files { relative, title, if *kind { "file" } else { "folder" }, - match ext { - Some(ext) => ext, - None => "", - }, + ext.as_ref().map_or("", |ext| ext), base )?; } diff --git a/viz-handlers/src/serve/error.rs b/viz-handlers/src/serve/error.rs index b3f10cf5..8d332f56 100644 --- a/viz-handlers/src/serve/error.rs +++ b/viz-handlers/src/serve/error.rs @@ -28,11 +28,11 @@ impl IntoResponse for Error { fn into_response(self) -> Response { ( match self { - Error::MethodNotAllowed => StatusCode::METHOD_NOT_ALLOWED, - Error::InvalidPath => StatusCode::BAD_REQUEST, - Error::PreconditionFailed => StatusCode::PRECONDITION_FAILED, - Error::RangeUnsatisfied(_) => StatusCode::RANGE_NOT_SATISFIABLE, - Error::Io(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::MethodNotAllowed => StatusCode::METHOD_NOT_ALLOWED, + Self::InvalidPath => StatusCode::BAD_REQUEST, + Self::PreconditionFailed => StatusCode::PRECONDITION_FAILED, + Self::RangeUnsatisfied(_) => StatusCode::RANGE_NOT_SATISFIABLE, + Self::Io(_) => StatusCode::INTERNAL_SERVER_ERROR, }, self.to_string(), ) diff --git a/viz-macros/tests/handler.rs b/viz-macros/tests/handler.rs index e4b2b692..eeb37cb2 100644 --- a/viz-macros/tests/handler.rs +++ b/viz-macros/tests/handler.rs @@ -11,7 +11,7 @@ impl FromRequest for Foo { type Error = Error; async fn extract(_: &mut Request) -> Result { - Ok(Foo) + Ok(Self) } } @@ -22,7 +22,7 @@ impl FromRequest for Bar { type Error = Error; async fn extract(_: &mut Request) -> Result { - Ok(Bar) + Ok(Self) } } @@ -30,7 +30,7 @@ struct MyError(String); impl From for Error { fn from(MyError(err): MyError) -> Self { - Error::Responder((StatusCode::INTERNAL_SERVER_ERROR, err).into_response()) + Self::Responder((StatusCode::INTERNAL_SERVER_ERROR, err).into_response()) } } @@ -92,28 +92,28 @@ fn cc(_: Foo, _: Bar) -> Result { } #[handler] -fn dd() {} +const fn dd() {} #[handler] -fn ee() -> StatusCode { +const fn ee() -> StatusCode { StatusCode::OK } #[handler] -fn ff() -> (StatusCode, &'static str) { +const fn ff() -> (StatusCode, &'static str) { (StatusCode::OK, "Hello, World!") } #[handler] -fn gg() {} +const fn gg() {} #[handler] -fn hh(_: Foo) -> Result<()> { +const fn hh(_: Foo) -> Result<()> { Ok(()) } #[handler] -fn ii(_: Foo) -> Result { +const fn ii(_: Foo) -> Result { Ok(StatusCode::OK) } diff --git a/viz-router/src/resources.rs b/viz-router/src/resources.rs index 453ba2c0..15c4cbfb 100644 --- a/viz-router/src/resources.rs +++ b/viz-router/src/resources.rs @@ -9,7 +9,7 @@ use crate::Route; /// A Kind for generating Resources path. #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) enum Kind { +enum Kind { /// index | create Empty, /// new: `new` @@ -27,7 +27,7 @@ pub(crate) enum Kind { pub struct Resources { name: String, singular: bool, - pub(crate) routes: Vec<(Kind, Route)>, + routes: Vec<(Kind, Route)>, } impl Resources { @@ -43,7 +43,7 @@ impl Resources { /// Without referencing an ID for a resource. #[must_use] - pub fn singular(mut self) -> Self { + pub const fn singular(mut self) -> Self { self.singular = true; self } @@ -69,7 +69,7 @@ impl Resources { self } - pub(crate) fn on(mut self, kind: Kind, method: Method, handler: H) -> Self + fn on(mut self, kind: Kind, method: Method, handler: H) -> Self where H: Handler> + Clone, O: IntoResponse, @@ -269,7 +269,7 @@ mod tests { struct Logger; impl Logger { - fn new() -> Self { + const fn new() -> Self { Self } } diff --git a/viz-router/src/route.rs b/viz-router/src/route.rs index 94089c7e..a91ffa09 100644 --- a/viz-router/src/route.rs +++ b/viz-router/src/route.rs @@ -44,7 +44,7 @@ pub struct Route { impl Route { /// Creates a new route. #[must_use] - pub fn new() -> Self { + pub const fn new() -> Self { Self { methods: Vec::new(), } @@ -234,7 +234,7 @@ mod tests { struct Logger; impl Logger { - fn new() -> Self { + const fn new() -> Self { Self } } diff --git a/viz-router/src/router.rs b/viz-router/src/router.rs index 291607c9..9b2cd793 100644 --- a/viz-router/src/router.rs +++ b/viz-router/src/router.rs @@ -28,7 +28,7 @@ pub struct Router { impl Router { /// Creates an empty `Router`. #[must_use] - pub fn new() -> Self { + pub const fn new() -> Self { Self { routes: None } } @@ -198,7 +198,7 @@ mod tests { struct Logger; impl Logger { - fn new() -> Self { + const fn new() -> Self { Self } } diff --git a/viz-router/src/tree.rs b/viz-router/src/tree.rs index df2fe635..97fe3bde 100644 --- a/viz-router/src/tree.rs +++ b/viz-router/src/tree.rs @@ -44,7 +44,7 @@ impl AsMut)>> for Tree { impl From for Tree { fn from(router: Router) -> Self { - let mut tree = Tree::default(); + let mut tree = Self::default(); if let Some(routes) = router.routes { for (mut path, Route { methods }) in routes { if !path.starts_with('/') { diff --git a/viz-smol/Cargo.toml b/viz-smol/Cargo.toml index 60a75e89..5b24efc4 100644 --- a/viz-smol/Cargo.toml +++ b/viz-smol/Cargo.toml @@ -44,8 +44,8 @@ session = ["cookie", "cookie-private", "viz-core/session"] csrf = ["cookie", "cookie-private", "viz-core/csrf"] cors = ["viz-core/cors"] -http1 = ["hyper/http1"] -http2 = ["hyper/http2"] +http1 = ["dep:hyper", "dep:hyper-util", "hyper?/http1", "hyper-util?/http1"] +http2 = ["dep:hyper", "dep:hyper-util", "hyper?/http2", "hyper-util?/http2"] unix-socket = [] @@ -64,8 +64,9 @@ viz-router.workspace = true viz-handlers = { workspace = true, optional = true } viz-macros = { workspace = true, optional = true } -hyper.workspace = true -hyper-util.workspace = true +hyper = { workspace = true, optional = true } +hyper-util = { workspace = true, optional = true } + tracing.workspace = true async-executor.workspace = true diff --git a/viz-smol/src/lib.rs b/viz-smol/src/lib.rs index 70fd9682..6dfa3500 100644 --- a/viz-smol/src/lib.rs +++ b/viz-smol/src/lib.rs @@ -63,8 +63,8 @@ pub use listener::Listener; mod server; pub use server::serve; -#[cfg(any(feature = "native_tls", feature = "rustls"))] -pub use server::tls; +// #[cfg(any(feature = "native-tls", feature = "rustls"))] +// pub use server::tls; pub use viz_core::*; pub use viz_router::*; diff --git a/viz-smol/src/server.rs b/viz-smol/src/server.rs index b2360cff..c9f80f72 100644 --- a/viz-smol/src/server.rs +++ b/viz-smol/src/server.rs @@ -3,6 +3,7 @@ use std::{borrow::Borrow, fmt::Debug, io, sync::Arc}; use async_executor::Executor; use futures_lite::io::{AsyncRead, AsyncWrite}; use hyper::rt::Timer; +#[cfg(any(feature = "http1", feature = "http2"))] use hyper_util::server::conn::auto::Builder; use smol_hyper::rt::{FuturesIo, SmolExecutor, SmolTimer}; @@ -14,9 +15,9 @@ mod tcp; #[cfg(all(unix, feature = "unix-socket"))] mod unix; -/// TLS -#[cfg(any(feature = "native_tls", feature = "rustls"))] -pub mod tls; +// TLS +// #[cfg(any(feature = "native-tls", feature = "rustls"))] +// pub mod tls; /// Serve a server with smol's networking types. #[allow(clippy::missing_errors_doc)] @@ -55,7 +56,9 @@ where let executor = executor.clone(); async move { let mut builder = Builder::new(SmolExecutor::new(AsRefExecutor(executor.borrow()))); + #[cfg(feature = "http1")] builder.http1().timer(SmolTimer::new()); + #[cfg(feature = "http2")] builder.http2().timer(SmolTimer::new()); if let Err(err) = builder.serve_connection_with_upgrades(io, responder).await { diff --git a/viz-smol/src/server/tcp.rs b/viz-smol/src/server/tcp.rs index 2eeb4e85..9763a7d7 100644 --- a/viz-smol/src/server/tcp.rs +++ b/viz-smol/src/server/tcp.rs @@ -7,10 +7,10 @@ impl crate::Listener for TcpListener { type Addr = SocketAddr; fn accept(&self) -> impl Future> + Send { - TcpListener::accept(self) + Self::accept(self) } fn local_addr(&self) -> Result { - TcpListener::local_addr(self) + Self::local_addr(self) } } diff --git a/viz-smol/src/server/unix.rs b/viz-smol/src/server/unix.rs index 29313d71..2c7d2534 100644 --- a/viz-smol/src/server/unix.rs +++ b/viz-smol/src/server/unix.rs @@ -7,10 +7,10 @@ impl crate::Listener for UnixListener { type Addr = SocketAddr; fn accept(&self) -> impl Future> + Send { - UnixListener::accept(self) + Self::accept(self) } fn local_addr(&self) -> Result { - UnixListener::local_addr(self) + Self::local_addr(self) } } diff --git a/viz-tower/src/layer.rs b/viz-tower/src/layer.rs index fa3978e8..6a0843ac 100644 --- a/viz-tower/src/layer.rs +++ b/viz-tower/src/layer.rs @@ -6,7 +6,7 @@ pub struct Layered(L); impl Layered { /// Creates a new tower layer. - pub fn new(l: L) -> Self { + pub const fn new(l: L) -> Self { Self(l) } } diff --git a/viz-tower/src/lib.rs b/viz-tower/src/lib.rs index 94e45b26..b080ca30 100644 --- a/viz-tower/src/lib.rs +++ b/viz-tower/src/lib.rs @@ -18,7 +18,7 @@ pub struct ServiceHandler(S); impl ServiceHandler { /// Creates a new [`ServiceHandler`]. - pub fn new(s: S) -> Self { + pub const fn new(s: S) -> Self { Self(s) } } diff --git a/viz-tower/src/middleware.rs b/viz-tower/src/middleware.rs index 1f868f44..12fe81ad 100644 --- a/viz-tower/src/middleware.rs +++ b/viz-tower/src/middleware.rs @@ -12,7 +12,7 @@ pub struct Middleware { impl Middleware { /// Creates a new tower middleware. - pub fn new(l: L, h: H) -> Self { + pub const fn new(l: L, h: H) -> Self { Self { l, h } } } diff --git a/viz-tower/src/service.rs b/viz-tower/src/service.rs index 875e6e14..94f985ca 100644 --- a/viz-tower/src/service.rs +++ b/viz-tower/src/service.rs @@ -12,7 +12,7 @@ pub struct HandlerService(H); impl HandlerService { /// Creates a new [`HandlerService`]. - pub fn new(h: H) -> Self { + pub const fn new(h: H) -> Self { Self(h) } } @@ -22,7 +22,7 @@ where H: Clone, { fn clone(&self) -> Self { - HandlerService(self.0.clone()) + Self(self.0.clone()) } } diff --git a/viz/Cargo.toml b/viz/Cargo.toml index 68b86b85..3318cec9 100644 --- a/viz/Cargo.toml +++ b/viz/Cargo.toml @@ -51,8 +51,8 @@ cors = ["viz-core/cors"] compression = ["viz-core/compression"] -http1 = ["hyper/http1"] -http2 = ["hyper/http2"] +http1 = ["dep:hyper", "dep:hyper-util", "hyper?/http1", "hyper-util?/http1"] +http2 = ["dep:hyper", "dep:hyper-util", "hyper?/http2", "hyper-util?/http2"] unix-socket = [] @@ -76,16 +76,16 @@ viz-router.workspace = true viz-handlers = { workspace = true, optional = true } viz-macros = { workspace = true, optional = true } -hyper.workspace = true -hyper-util.workspace = true +hyper = { workspace = true, optional = true } +hyper-util = { workspace = true, optional = true } futures-util = { workspace = true, optional = true } tracing.workspace = true rustls-pemfile = { workspace = true, optional = true } - tokio-native-tls = { workspace = true, optional = true } tokio-rustls = { workspace = true, optional = true } + tokio = { workspace = true, features = ["macros"] } tokio-util = { workspace = true, features = ["net"] } diff --git a/viz/src/lib.rs b/viz/src/lib.rs index b110a694..abd1a6c9 100644 --- a/viz/src/lib.rs +++ b/viz/src/lib.rs @@ -531,7 +531,7 @@ pub use listener::Listener; mod server; pub use server::{serve, Server}; -#[cfg(any(feature = "native_tls", feature = "rustls"))] +#[cfg(any(feature = "native-tls", feature = "rustls"))] pub use server::tls; pub use viz_core::*; diff --git a/viz/src/server.rs b/viz/src/server.rs index bf61ba60..7a9e46c3 100644 --- a/viz/src/server.rs +++ b/viz/src/server.rs @@ -7,6 +7,7 @@ use std::{ }; use hyper_util::rt::{TokioExecutor, TokioIo}; +#[cfg(any(feature = "http1", feature = "http2"))] use hyper_util::server::conn::auto::Builder; use tokio::{ io::{AsyncRead, AsyncWrite}, @@ -17,7 +18,7 @@ use tokio::{ use crate::{future::FutureExt, Listener, Responder, Router}; /// TLS -#[cfg(any(feature = "native_tls", feature = "rustls"))] +#[cfg(any(feature = "native-tls", feature = "rustls"))] pub mod tls; #[cfg(any(feature = "http1", feature = "http2"))] diff --git a/viz/src/server/tcp.rs b/viz/src/server/tcp.rs index 83abd09e..ba622e3b 100644 --- a/viz/src/server/tcp.rs +++ b/viz/src/server/tcp.rs @@ -7,10 +7,10 @@ impl super::Listener for TcpListener { type Addr = SocketAddr; fn accept(&self) -> impl Future> + Send { - TcpListener::accept(self) + Self::accept(self) } fn local_addr(&self) -> Result { - TcpListener::local_addr(self) + Self::local_addr(self) } } diff --git a/viz/src/server/tls.rs b/viz/src/server/tls.rs index 2e32725a..e07f9c8e 100644 --- a/viz/src/server/tls.rs +++ b/viz/src/server/tls.rs @@ -17,7 +17,7 @@ pub struct TlsListener { impl TlsListener { /// Creates a new TLS listener. - pub fn new(t: T, a: A) -> Self { + pub const fn new(t: T, a: A) -> Self { Self { inner: t, acceptor: a, @@ -25,12 +25,12 @@ impl TlsListener { } /// Gets the listener. - pub fn get_ref(&self) -> &T { + pub const fn get_ref(&self) -> &T { &self.inner } /// Gets the acceptor. - pub fn get_acceptor(&self) -> &A { + pub const fn get_acceptor(&self) -> &A { &self.acceptor } } diff --git a/viz/src/server/tls/rustls.rs b/viz/src/server/tls/rustls.rs index 1a84a25c..8498ee0d 100644 --- a/viz/src/server/tls/rustls.rs +++ b/viz/src/server/tls/rustls.rs @@ -5,12 +5,7 @@ use std::{ use tokio::net::{TcpListener, TcpStream}; use tokio_rustls::{ - rustls::{ - server::{ - AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth, - }, - Certificate, PrivateKey, RootCertStore, ServerConfig, - }, + rustls::{pki_types::PrivateKeyDer, server::WebPkiClientVerifier, RootCertStore, ServerConfig}, server::TlsStream, }; @@ -95,26 +90,29 @@ impl Config { /// /// # Errors pub fn build(self) -> Result { - fn read_trust_anchor(trust_anchor: &Certificate) -> Result { + fn read_trust_anchor(mut trust_anchor: &[u8]) -> Result { + let certs = rustls_pemfile::certs(&mut trust_anchor) + .collect::>>() + .map_err(Error::boxed)?; let mut store = RootCertStore::empty(); - store.add(trust_anchor).map_err(Error::boxed)?; + for cert in certs { + store.add(cert).map_err(Error::boxed)?; + } Ok(store) } let certs = rustls_pemfile::certs(&mut self.cert.as_slice()) - .map(|mut certs| certs.drain(..).map(Certificate).collect()) + .collect::, _>>() .map_err(Error::boxed)?; let keys = { - let mut pkcs8: Vec = - rustls_pemfile::pkcs8_private_keys(&mut self.key.as_slice()) - .map(|mut keys| keys.drain(..).map(PrivateKey).collect()) - .map_err(Error::boxed)?; + let mut pkcs8 = rustls_pemfile::pkcs8_private_keys(&mut self.key.as_slice()) + .collect::, _>>() + .map_err(Error::boxed)?; if pkcs8.is_empty() { - let mut rsa: Vec = - rustls_pemfile::rsa_private_keys(&mut self.key.as_slice()) - .map(|mut keys| keys.drain(..).map(PrivateKey).collect()) - .map_err(Error::boxed)?; + let mut rsa = rustls_pemfile::rsa_private_keys(&mut self.key.as_slice()) + .collect::, _>>() + .map_err(Error::boxed)?; if rsa.is_empty() { return Err(Error::boxed(IoError::new( @@ -122,28 +120,30 @@ impl Config { "failed to parse tls private keys", ))); } - rsa.remove(0) + PrivateKeyDer::Pkcs1(rsa.remove(0)) } else { - pkcs8.remove(0) + PrivateKeyDer::Pkcs8(pkcs8.remove(0)) } }; let client_auth = match self.client_auth { - ClientAuth::Off => NoClientAuth::boxed(), - ClientAuth::Optional(trust_anchor) => AllowAnyAnonymousOrAuthenticatedClient::new( - read_trust_anchor(&Certificate(trust_anchor))?, - ) - .boxed(), + ClientAuth::Off => WebPkiClientVerifier::no_client_auth(), + ClientAuth::Optional(trust_anchor) => { + WebPkiClientVerifier::builder(read_trust_anchor(&trust_anchor)?.into()) + .allow_unauthenticated() + .build() + .map_err(Error::boxed)? + } ClientAuth::Required(trust_anchor) => { - AllowAnyAuthenticatedClient::new(read_trust_anchor(&Certificate(trust_anchor))?) - .boxed() + WebPkiClientVerifier::builder(read_trust_anchor(&trust_anchor)?.into()) + .build() + .map_err(Error::boxed)? } }; ServerConfig::builder() - .with_safe_defaults() .with_client_cert_verifier(client_auth) - .with_single_cert_with_ocsp_and_sct(certs, keys, self.ocsp_resp, Vec::new()) + .with_single_cert_with_ocsp(certs, keys, self.ocsp_resp) .map_err(Error::boxed) } } diff --git a/viz/src/server/unix.rs b/viz/src/server/unix.rs index 2b1cff14..b6d2f580 100644 --- a/viz/src/server/unix.rs +++ b/viz/src/server/unix.rs @@ -7,10 +7,10 @@ impl super::Listener for UnixListener { type Addr = SocketAddr; fn accept(&self) -> impl Future> + Send { - UnixListener::accept(self) + Self::accept(self) } fn local_addr(&self) -> Result { - UnixListener::local_addr(self) + Self::local_addr(self) } }