Skip to content

Commit

Permalink
Improve document (salvo-rs#1070)
Browse files Browse the repository at this point in the history
* Improve document

* Format Rust code using rustfmt

* u

* wip

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
chrislearn and github-actions[bot] authored Mar 2, 2025
1 parent 09baa3f commit ee957b6
Show file tree
Hide file tree
Showing 21 changed files with 415 additions and 161 deletions.
14 changes: 11 additions & 3 deletions crates/extra/src/affix_state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//! Middleware for add any data to depot.
//! Middleware for adding shared application state to the request context.
//!
//! This middleware allows you to inject any data into the Depot, making it
//! available to all subsequent handlers in the request pipeline. This is useful
//! for sharing configuration, database connections, and other application state.
//!
//! # Example
//!
Expand Down Expand Up @@ -76,15 +80,19 @@ where
}
}

/// Inject a value into depot.
/// Inject a typed value into depot using the type's ID as the key.
///
/// This is useful when you want to access the value by its type rather than by an explicit key.
///
/// View [module level documentation](index.html) for more details.
#[inline]
pub fn inject<V: Send + Sync + Clone + 'static>(value: V) -> AffixList {
insert(format!("{:?}", TypeId::of::<V>()), value)
}

/// Insert a key-value pair into depot.
/// Insert a key-value pair into depot with an explicit key.
///
/// Use this when you need to access the value using a specific key string.
///
/// View [module level documentation](index.html) for more details.
#[inline]
Expand Down
17 changes: 12 additions & 5 deletions crates/extra/src/basic_auth.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! Middleware for basic authentication.
//! Middleware for HTTP Basic Authentication.
//!
//! This middleware implements the standard HTTP Basic Authentication scheme as described in RFC 7617.
//! It extracts credentials from the Authorization header and validates them against your custom validator.
//!
//! # Example
//!
Expand Down Expand Up @@ -35,14 +38,18 @@ use salvo_core::{async_trait, Depot, Error, FlowCtrl, Handler};
/// key used when insert into depot.
pub const USERNAME_KEY: &str = "::salvo::basic_auth::username";

/// BasicAuthValidator
/// Validator for Basic Authentication credentials.
pub trait BasicAuthValidator: Send + Sync {
/// Validate is that username and password is right.
/// Validates whether the provided username and password are correct.
///
/// Implement this method to check credentials against your authentication system.
/// Return `true` if authentication succeeds, `false` otherwise.
fn validate(&self, username: &str, password: &str, depot: &mut Depot) -> impl Future<Output = bool> + Send;
}
/// BasicAuthDepotExt

/// Extension trait for retrieving the authenticated username from a Depot.
pub trait BasicAuthDepotExt {
/// Get basic auth username reference.
/// Returns the authenticated username if authentication was successful.
fn basic_auth_username(&self) -> Option<&str>;
}

Expand Down
10 changes: 7 additions & 3 deletions crates/extra/src/caching_headers.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Middleware for etag and last-modified-since headers.
//! Middleware for handling ETag and Last-Modified headers.
//!
//! This crate provides three handlers: [`ETag`], [`Modified`], and [`CachingHeaders`].
//! Unless you are sure that you _don't_ want either etag or last-modified
//! behavior, please use the combined [`CachingHeaders`] handler.
//! Unless you are sure that you _don't_ want either ETag or Last-Modified
//! behavior, use the combined [`CachingHeaders`] handler for better cache control.
use etag::EntityTag;
use salvo_core::http::header::{ETAG, IF_NONE_MATCH};
Expand Down Expand Up @@ -157,6 +157,10 @@ impl Handler for Modified {
}

/// A combined handler that provides both [`ETag`] and [`Modified`] behavior.
///
/// This handler helps improve performance by preventing unnecessary data transfers
/// when a client already has the latest version of a resource, as determined by
/// either ETag or Last-Modified comparisons.
#[derive(Clone, Debug, Copy, Default)]
pub struct CachingHeaders(Modified, ETag);

Expand Down
5 changes: 4 additions & 1 deletion crates/extra/src/catch_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ use salvo_core::http::{Request, Response, StatusError};
use salvo_core::{async_trait, Depot, FlowCtrl, Error, Handler};


/// Middleware for catch panic in handlers.
/// Middleware that catches panics in handlers and converts them to HTTP 500 responses.
///
/// This middleware should be registered as the first middleware in your router chain
/// to ensure it catches panics from all subsequent handlers and middlewares.
///
/// View [module level documentation](index.html) for more details.
#[derive(Default, Debug)]
Expand Down
7 changes: 4 additions & 3 deletions crates/extra/src/concurrency_limiter.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Middleware for limit concurrency.
//! Middleware for limiting concurrency.
//!
//! Limit the max number of requests being concurrently processed.
//! This middleware limits the maximum number of requests being processed concurrently,
//! which helps prevent server overload during traffic spikes.
//!
//! Example:
//! # Example
//!
//! ```no_run
//! use std::fs::create_dir_all;
Expand Down
10 changes: 5 additions & 5 deletions crates/flash/src/session_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{Flash, FlashHandler, FlashStore};
#[derive(Debug)]
#[non_exhaustive]
pub struct SessionStore {
/// The cookie name for the flash messages.
/// The session key for the flash messages.
pub name: String,
}
impl Default for SessionStore {
Expand All @@ -24,13 +24,13 @@ impl SessionStore {
}
}

/// Sets cookie name.
/// Sets session key name.
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self
}

/// Into `FlashHandler`.
/// Converts into `FlashHandler`.
pub fn into_handler(self) -> FlashHandler<SessionStore> {
FlashHandler::new(self)
}
Expand All @@ -43,13 +43,13 @@ impl FlashStore for SessionStore {
async fn save_flash(&self, _req: &mut Request, depot: &mut Depot, _res: &mut Response, flash: Flash) {
if let Err(e) = depot
.session_mut()
.expect("session must be exist")
.expect("session must exist")
.insert(&self.name, flash)
{
tracing::error!(error = ?e, "save flash to session failed");
}
}
async fn clear_flash(&self, depot: &mut Depot, _res: &mut Response) {
depot.session_mut().expect("session must be exist").remove(&self.name);
depot.session_mut().expect("session must exist").remove(&self.name);
}
}
14 changes: 12 additions & 2 deletions crates/jwt-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,19 @@ Salvo is an extremely simple and powerful Rust web backend framework. Only basic

# salvo-jwt-auth

## Jwt auth middleware for Salvo.
JWT (JSON Web Token) authentication middleware for the Salvo web framework.

This is an official crate, so you can enable it in `Cargo.toml` like this:
## Features

- **Flexible token extraction**: Extract tokens from headers, query parameters, cookies, or form data
- **Multiple authentication strategies**: Use either static keys or OpenID Connect for token validation
- **Easy integration**: Works seamlessly within Salvo's middleware system
- **Type-safe claims**: Decode tokens into your own custom claims structs
- **Configurable validation**: Customize token validation rules

## Installation

This is an official crate, so you can enable it in `Cargo.toml`:

```toml
salvo = { version = "*", features = ["jwt-auth"] }
Expand Down
51 changes: 41 additions & 10 deletions crates/jwt-auth/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,33 @@ use serde::Deserialize;

use salvo_core::Depot;

/// JwtAuthDecoder is used to decode a token into claims.
/// Trait for JWT token decoding and validation.
///
/// Implementors of this trait are responsible for decoding JWT tokens into claims objects
/// and performing any necessary validation. The `JwtAuth` middleware uses the configured
/// decoder to validate tokens extracted from requests.
///
/// The crate provides built-in implementations:
/// - `ConstDecoder`: Uses a static key for token validation
/// - `OidcDecoder`: Uses OpenID Connect for validation (requires the `oidc` feature)
pub trait JwtAuthDecoder {
/// Error type.
/// The error type returned if decoding or validation fails.
type Error: std::error::Error + Send + Sync + 'static;

///Decode token.
/// Decodes and validates a JWT token.
///
/// # Parameters
///
/// * `token` - The JWT token string to decode
/// * `depot` - The current request's depot, which can be used to store/retrieve additional data
///
/// # Type Parameters
///
/// * `C` - The claims type to deserialize from the token payload
///
/// # Returns
///
/// Returns a `Result` containing either the decoded token data or an error.
fn decode<C>(
&self,
token: &str,
Expand All @@ -19,41 +40,51 @@ pub trait JwtAuthDecoder {
C: for<'de> Deserialize<'de>;
}

/// ConstDecoder will decode token with a static secret.
/// A decoder that uses a constant key for JWT token validation.
///
/// This is the simplest decoder implementation, suitable for applications using
/// symmetric key signing (HMAC) or a single asymmetric key pair (RSA, ECDSA).
pub struct ConstDecoder {
/// Key used for validating JWT signatures
decoding_key: DecodingKey,

/// JWT validation parameters
validation: Validation,
}

impl ConstDecoder {
/// Create a new `ConstDecoder`.
/// Creates a new decoder with the given decoding key and default validation.
pub fn new(decoding_key: DecodingKey) -> Self {
Self {
decoding_key,
validation: Validation::default(),
}
}
/// Create a new `ConstDecoder` with validation.

/// Creates a new decoder with the given decoding key and custom validation parameters.
pub fn with_validation(decoding_key: DecodingKey, validation: Validation) -> Self {
Self {
decoding_key,
validation,
}
}

/// If you're using HMAC, use this.
/// Creates a decoder from a raw secret byte array for HMAC verification.
///
/// This is the most common method for symmetric key validation.
pub fn from_secret(secret: &[u8]) -> Self {
Self::with_validation(DecodingKey::from_secret(secret), Validation::default())
}

/// If you're using HMAC with a base64 encoded secret, use this.
/// Creates a decoder from a base64-encoded secret string for HMAC verification.
pub fn from_base64_secret(secret: &str) -> Result<Self, JwtError> {
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.
/// Creates a decoder from an RSA public key in PEM format.
///
/// Only available when the `use_pem` feature is enabled.
pub fn from_rsa_pem(key: &[u8]) -> Result<Self, JwtError> {
DecodingKey::from_rsa_pem(key)
.map(|key| Self::with_validation(key, Validation::new(Algorithm::RS256)))
Expand Down
Loading

0 comments on commit ee957b6

Please sign in to comment.