Skip to content

Commit

Permalink
docs(examples): Annotate a,b,g,h prefixed examples with code comments (
Browse files Browse the repository at this point in the history
  • Loading branch information
Jinzedev authored Feb 13, 2025
1 parent a2b3dd8 commit d4f64fb
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 21 deletions.
19 changes: 14 additions & 5 deletions examples/acme-http01-quinn/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
use salvo::prelude::*;

// Handler function that returns "Hello World" for any request
#[handler]
async fn hello() -> &'static str {
"Hello World"
}

#[tokio::main]
async fn main() {
// Initialize logging
tracing_subscriber::fmt().init();

// Create a router and register the hello handler
let mut router = Router::new().get(hello);

// Set up a TCP listener on port 443 for HTTPS
let listener = TcpListener::new("0.0.0.0:443")
.acme()
.cache_path("temp/letsencrypt")
.add_domain("test.salvo.rs") // Replace this domain name with your own.
.http01_challenge(&mut router)
.quinn("0.0.0.0:443");
.acme() // Enable ACME for automatic SSL certificate management
.cache_path("temp/letsencrypt") // Path to store the certificate cache
.add_domain("test.salvo.rs") // replace with your domain
.http01_challenge(&mut router) // Add routes to handle ACME challenge requests
.quinn("0.0.0.0:443"); // Enable QUIC/HTTP3 support on the same port

// Create an acceptor that listens on both port 80 (HTTP) and port 443 (HTTPS)
let acceptor = listener.join(TcpListener::new("0.0.0.0:80")).bind().await;

// Start the server with the configured acceptor and router
Server::new(acceptor).serve(router).await;
}
19 changes: 15 additions & 4 deletions examples/acme-http01/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
use salvo::prelude::*;

// This handler function responds with "Hello World" to any incoming request
#[handler]
async fn hello() -> &'static str {
"Hello World"
}

#[tokio::main]
async fn main() {
// Initialize the tracing subscriber for logging
tracing_subscriber::fmt().init();

// Create a new router and register the hello handler
let mut router = Router::new().get(hello);

// Set up a TCP listener on port 443 for HTTPS
let listener = TcpListener::new("0.0.0.0:443")
.acme()
.acme() // Enable ACME for automatic SSL certificate management
// Use Let's Encrypt production server by default
// Uncomment the following line to use the staging server for testing purposes
// .directory("letsencrypt", salvo::conn::acme::LETS_ENCRYPT_STAGING)
.cache_path("/temp/letsencrypt")
.add_domain("test.salvo.rs") // Replace this domain name with your own.
.http01_challenge(&mut router);
.cache_path("/temp/letsencrypt") // Specify the path to store the certificate cache
.add_domain("test.salvo.rs") // replace with your domain
.http01_challenge(&mut router); // Add routes to handle ACME challenge requests

// Create an acceptor that listens on both port 80 (HTTP) and port 443 (HTTPS)
let acceptor = listener.join(TcpListener::new("0.0.0.0:80")).bind().await;

// Start the server with the configured acceptor and router
Server::new(acceptor).serve(router).await;
}
13 changes: 10 additions & 3 deletions examples/acme-tls-alpn01/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
use salvo::prelude::*;

// This handler function responds with "Hello World" to any incoming request
#[handler]
async fn hello() -> &'static str {
"Hello World"
}

#[tokio::main]
async fn main() {
// Initialize the tracing subscriber for logging
tracing_subscriber::fmt().init();

// Create a new router and register the hello handler
let router = Router::new().get(hello);

// Set up a TCP listener on port 443 for HTTPS
let acceptor = TcpListener::new("0.0.0.0:443")
.acme()
// .cache_path("temp/letsencrypt")
.add_domain("test.salvo.rs") // Replace this domain name with your own.
.acme() // Enable ACME for automatic SSL certificate management
// .cache_path("temp/letsencrypt") // Specify the path to store the certificate cache (uncomment if needed)
.add_domain("test.salvo.rs") // Replace this domain name with your own
.bind()
.await;

// Start the server with the configured acceptor and router
Server::new(acceptor).serve(router).await;
}
18 changes: 18 additions & 0 deletions examples/affix-state/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,64 @@ use std::sync::Mutex;

use salvo::prelude::*;

// Configuration structure with username and password
#[allow(dead_code)]
#[derive(Default, Clone, Debug)]
struct Config {
username: String,
password: String,
}

// State structure to hold a list of fail messages
#[derive(Default, Debug)]
struct State {
fails: Mutex<Vec<String>>,
}

#[handler]
async fn hello(depot: &mut Depot) -> String {
// Obtain the Config instance from the depot
let config = depot.obtain::<Config>().unwrap();
// Get custom data from the depot
let custom_data = depot.get::<&str>("custom_data").unwrap();
// Obtain the shared State instance from the depot
let state = depot.obtain::<Arc<State>>().unwrap();
// Lock the fails vector and add a new fail message
let mut fails_ref = state.fails.lock().unwrap();
fails_ref.push("fail message".into());
// Format and return the response string
format!("Hello World\nConfig: {config:#?}\nFails: {fails_ref:#?}\nCustom Data: {custom_data}")
}

#[tokio::main]
async fn main() {
// Initialize the tracing subscriber for logging
tracing_subscriber::fmt().init();

// Create a Config instance with default username and password
let config = Config {
username: "root".to_string(),
password: "pwd".to_string(),
};

// Set up the router with state injection and custom data
let router = Router::new()
// Use hoop to inject middleware and data into the request context
.hoop(
affix_state::inject(config)
// Inject a shared State instance into the request context
.inject(Arc::new(State {
fails: Mutex::new(Vec::new()),
}))
// Insert custom data into the request context
.insert("custom_data", "I love this world!"),
)
// Register the hello handler for the root path
.get(hello)
// Add an additional route for the path "/hello" with the same handler
.push(Router::with_path("hello").get(hello));

// Bind the server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
26 changes: 20 additions & 6 deletions examples/basic-auth/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
use salvo::basic_auth::{BasicAuth, BasicAuthValidator};
use salvo::prelude::*;

// Custom validator implementing BasicAuthValidator trait
struct Validator;
impl BasicAuthValidator for Validator {
// Validate username and password combination
async fn validate(&self, username: &str, password: &str, _depot: &mut Depot) -> bool {
username == "root" && password == "pwd"
}
}

// Simple handler that returns "Hello" for authenticated requests
#[handler]
async fn hello() -> &'static str {
"Hello"
}

// Create router with basic authentication middleware
fn route() -> Router {
// Initialize basic authentication handler with our validator
let auth_handler = BasicAuth::new(Validator);
// Apply authentication middleware to the router
Router::with_hoop(auth_handler).goal(hello)
}

#[tokio::main]
async fn main() {
// Initialize logging
tracing_subscriber::fmt().init();

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(route()).await;
}
Expand All @@ -32,24 +41,29 @@ mod tests {

#[tokio::test]
async fn test_basic_auth() {
// Create a service instance from our router for testing purposes
let service = Service::new(super::route());

// Test case 1: Verify successful authentication with valid credentials
let content = TestClient::get("http://0.0.0.0:5800/")
.basic_auth("root", Some("pwd"))
.send(&service)
.basic_auth("root", Some("pwd")) // Use correct username/password
.send(&service) // Send the request to the service
.await
.take_string()
.take_string() // Extract response body as string
.await
.unwrap();
// Verify response contains expected "Hello" message
assert!(content.contains("Hello"));

// Test case 2: Verify authentication failure with invalid password
let content = TestClient::get("http://0.0.0.0:5800/")
.basic_auth("root", Some("pwd2"))
.send(&service)
.basic_auth("root", Some("pwd2")) // Use incorrect password
.send(&service) // Send the request to the service
.await
.take_string()
.take_string() // Extract response body as string
.await
.unwrap();
// Verify response contains "Unauthorized" error
assert!(content.contains("Unauthorized"));
}
}
12 changes: 12 additions & 0 deletions examples/body-channel/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
use salvo::prelude::*;

// Handler demonstrating streaming response using response channel
#[handler]
async fn hello(res: &mut Response) {
// Set response content type to plain text
res.add_header("content-type", "text/plain", true).unwrap();

// Create a channel for streaming response data
let mut tx = res.channel();

// Spawn async task to send data through the channel
tokio::spawn(async move {
tx.send_data("Hello world").await.unwrap();
});
}

#[tokio::main]
async fn main() {
// Initialize logging subsystem
tracing_subscriber::fmt().init();

// Bind server to port 5800
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;

// Create router with single endpoint
let router = Router::new().get(hello);

// Start serving requests
Server::new(acceptor).serve(router).await;
}
8 changes: 8 additions & 0 deletions examples/graceful-shutdown/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,32 @@ use tokio::signal;

#[tokio::main]
async fn main() {
// Bind server to port 5800
let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
// Create server instance
let server = Server::new(acceptor);
// Get server handle for graceful shutdown
let handle = server.handle();

// Listen Shutdown Signal
tokio::spawn(listen_shutdown_signal(handle));

// Start serving requests (empty router in this example)
server.serve(Router::new()).await;
}

async fn listen_shutdown_signal(handle: ServerHandle) {
// Wait Shutdown Signal
let ctrl_c = async {
// Handle Ctrl+C signal
signal::ctrl_c()
.await
.expect("failed to install Ctrl+C handler");
};

#[cfg(unix)]
let terminate = async {
// Handle SIGTERM on Unix systems
signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("failed to install signal handler")
.recv()
Expand All @@ -32,12 +38,14 @@ async fn listen_shutdown_signal(handle: ServerHandle) {

#[cfg(windows)]
let terminate = async {
// Handle Ctrl+C on Windows (alternative implementation)
signal::windows::ctrl_c()
.expect("failed to install signal handler")
.recv()
.await;
};

// Wait for either signal to be received
tokio::select! {
_ = ctrl_c => println!("ctrl_c signal received"),
_ = terminate => println!("terminate signal received"),
Expand Down
25 changes: 22 additions & 3 deletions examples/hello-h3/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
use salvo::conn::rustls::{Keycert, RustlsConfig};
use salvo::prelude::*;

// Handler function responding with "Hello World" for HTTP/3 requests
#[handler]
async fn hello() -> &'static str {
"Hello World"
}

#[tokio::main]
async fn main() {
// Initialize logging system
tracing_subscriber::fmt().init();

// Load TLS certificate and private key from embedded PEM files
let cert = include_bytes!("../certs/cert.pem").to_vec();
let key = include_bytes!("../certs/key.pem").to_vec();

// Create router with single endpoint
let router = Router::new().get(hello);
let config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));
let listener = TcpListener::new(("0.0.0.0", 5800)).rustls(config.clone());

// Configure TLS settings using Rustls
let config = RustlsConfig::new(
Keycert::new()
.cert(cert.as_slice())
.key(key.as_slice())
);

let acceptor = QuinnListener::new(config.build_quinn_config().unwrap(), ("0.0.0.0", 5800))
// Create TCP listener with TLS encryption on port 5800
let listener = TcpListener::new(("0.0.0.0", 5800))
.rustls(config.clone());

// Create QUIC listener and combine with TCP listener
let acceptor = QuinnListener::new(
config.build_quinn_config().unwrap(),
("0.0.0.0", 5800)
)
.join(listener)
.bind()
.await;

// Start server supporting both HTTP/3 (QUIC) and HTTPS (TCP)
Server::new(acceptor).serve(router).await;
}
Loading

0 comments on commit d4f64fb

Please sign in to comment.