Skip to content

Commit

Permalink
docs(examples): Annotate c,d prefixed examples with code comments (#1057
Browse files Browse the repository at this point in the history
)

* docs(examples): Annotate a,b,g,h prefixed examples with code comments

* docs(examples): Annotate c,d,gprefixed examples with code comments
  • Loading branch information
Jinzedev authored Feb 13, 2025
1 parent 5e9c7ef commit d5d0abc
Show file tree
Hide file tree
Showing 26 changed files with 347 additions and 23 deletions.
17 changes: 17 additions & 0 deletions examples/cache-simple/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ use salvo::prelude::*;
use salvo::writing::Text;
use time::OffsetDateTime;

// Handler for serving the home page with HTML content
#[handler]
async fn home() -> Text<&'static str> {
Text::Html(HOME_HTML)
}

// Handler for short-lived cached response (5 seconds)
#[handler]
async fn short() -> String {
format!(
"Hello World, my birth time is {}",
OffsetDateTime::now_utc()
)
}

// Handler for long-lived cached response (1 minute)
#[handler]
async fn long() -> String {
format!(
Expand All @@ -26,28 +31,40 @@ async fn long() -> String {

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

// Create cache middleware for short-lived responses (5 seconds TTL)
let short_cache = Cache::new(
MokaStore::builder()
.time_to_live(Duration::from_secs(5))
.build(),
RequestIssuer::default(),
);

// Create cache middleware for long-lived responses (60 seconds TTL)
let long_cache = Cache::new(
MokaStore::builder()
.time_to_live(Duration::from_secs(60))
.build(),
RequestIssuer::default(),
);

// Set up router with three endpoints:
// - / : Home page
// - /short : Response cached for 5 seconds
// - /long : Response cached for 1 minute
let router = Router::new()
.get(home)
.push(Router::with_path("short").hoop(short_cache).get(short))
.push(Router::with_path("long").hoop(long_cache).get(long));

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}

// HTML template for the home page with links to cached endpoints
static HOME_HTML: &str = r#"
<!DOCTYPE html>
<html>
Expand Down
9 changes: 7 additions & 2 deletions examples/caching-headers/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
use salvo::prelude::*;

// Handler that returns a simple "Hello World" response
#[handler]
async fn hello() -> &'static str {
"Hello World"
}

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

// CachingHeader must be before Compression.
// Set up router with caching headers and compression middleware
// CachingHeader must be before Compression to properly set cache control headers
let router = Router::with_hoop(CachingHeaders::new())
.hoop(Compression::new().min_length(0))
.hoop(Compression::new().min_length(0)) // Enable compression for all responses
.get(hello);

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
15 changes: 15 additions & 0 deletions examples/catch-error/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
use salvo::prelude::*;

// Custom error type for demonstration
struct CustomError;

// Implement Writer trait for CustomError to customize error response
#[async_trait]
impl Writer for CustomError {
async fn write(self, _req: &mut Request, _depot: &mut Depot, res: &mut Response) {
// Set response status code to 500 and custom error message
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
res.render("custom error");
}
}

// Handler that returns an anyhow error for testing error handling
#[handler]
async fn handle_anyhow() -> Result<(), anyhow::Error> {
Err(anyhow::anyhow!("handled anyhow error"))
}

// Handler that returns an eyre error for testing error handling
#[handler]
async fn handle_eyre() -> eyre::Result<()> {
Err(eyre::Report::msg("handled eyre error"))
}

// Handler that returns our custom error type
#[handler]
async fn handle_custom() -> Result<(), CustomError> {
Err(CustomError)
}

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

// Set up router with three error handling endpoints:
// - /anyhow : demonstrates anyhow error handling
// - /eyre : demonstrates eyre error handling
// - /custom : demonstrates custom error handling
let router = Router::new()
.push(Router::with_path("anyhow").get(handle_anyhow))
.push(Router::with_path("eyre").get(handle_eyre))
.push(Router::with_path("custom").get(handle_custom));

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
5 changes: 5 additions & 0 deletions examples/catch-panic/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use salvo::prelude::*;

// Handler that deliberately panics to demonstrate panic catching
#[handler]
async fn hello() {
panic!("panic error!");
}

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

// Set up router with CatchPanic middleware to handle panics gracefully
// This prevents the server from crashing when a panic occurs in a handler
let router = Router::new().hoop(CatchPanic::new()).get(hello);

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
10 changes: 10 additions & 0 deletions examples/compression/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,48 @@ use salvo::prelude::*;

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

// Print current working directory for debugging
println!("current_dir: {:?}", std::env::current_dir().unwrap());

// Set up base directory for static files
let base_dir = std::env::current_dir()
.unwrap()
.join("compression/static")
.canonicalize()
.unwrap();
println!("Base Dir: {base_dir:?}");

// Configure router with different compression settings for different paths
let router = Router::new()
// WebSocket chat with forced compression priority
.push(
Router::with_hoop(Compression::new().force_priority(true))
.path("ws_chat")
.get(StaticFile::new(base_dir.join("ws_chat.txt"))),
)
// SSE chat with Brotli compression
.push(
Router::with_hoop(Compression::new().enable_brotli(CompressionLevel::Fastest))
.path("sse_chat")
.get(StaticFile::new(base_dir.join("sse_chat.txt"))),
)
// Todos with Zstd compression
.push(
Router::with_hoop(Compression::new().enable_zstd(CompressionLevel::Fastest))
.path("todos")
.get(StaticFile::new(base_dir.join("todos.txt"))),
)
// All other paths with Gzip compression
.push(
Router::with_hoop(Compression::new().enable_gzip(CompressionLevel::Fastest))
.path("{*path}")
.get(StaticDir::new(base_dir)),
);

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
19 changes: 18 additions & 1 deletion examples/concurrency-limiter/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@ use std::path::Path;

use salvo::prelude::*;

// Handler for serving the index page with upload forms
#[handler]
async fn index(res: &mut Response) {
res.render(Text::Html(INDEX_HTML));
}

// Handler for processing file uploads with a simulated delay
#[handler]
async fn upload(req: &mut Request, res: &mut Response) {
// Extract file from the multipart form data
let file = req.file("file").await;
// Simulate a long-running operation (10 seconds)
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;

if let Some(file) = file {
// Generate destination path for the uploaded file
let dest = format!("temp/{}", file.name().unwrap_or("file"));
tracing::debug!(dest = %dest, "upload file");

// Copy file to destination
if let Err(e) = std::fs::copy(file.path(), Path::new(&dest)) {
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
res.render(Text::Plain(format!("file not found in request: {e}")));
Expand All @@ -28,23 +37,31 @@ async fn upload(req: &mut Request, res: &mut Response) {

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

// Create temporary directory for file uploads
create_dir_all("temp").unwrap();

// Configure router with two upload endpoints:
// - /limited: Only allows one concurrent upload (with concurrency limiter)
// - /unlimit: Allows unlimited concurrent uploads
let router = Router::new()
.get(index)
.push(
Router::new()
.hoop(max_concurrency(1))
.hoop(max_concurrency(1)) // Limit concurrent requests to 1
.path("limited")
.post(upload),
)
.push(Router::with_path("unlimit").post(upload));

// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}

// HTML template for the upload forms page
static INDEX_HTML: &str = r#"<!DOCTYPE html>
<html>
<head>
Expand Down
14 changes: 14 additions & 0 deletions examples/cors/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,54 @@ use salvo::prelude::*;

#[tokio::main]
async fn main() {
// Initialize logging system
tracing_subscriber::fmt().init();
// Start both backend and frontend servers concurrently
tokio::join!(backend_server(), frontend_server());
}

async fn backend_server() {
// Handler that returns a simple message for CORS demonstration
#[handler]
async fn hello() -> &'static str {
"hello, I am content from remote server."
}

// Configure CORS middleware with specific settings:
// - Allow requests from localhost:5800
// - Allow specific HTTP methods
// - Allow authorization header
let cors = Cors::new()
.allow_origin(["http://127.0.0.1:5800", "http://localhost:5800"])
.allow_methods(vec![Method::GET, Method::POST, Method::DELETE])
.allow_headers("authorization")
.into_handler();

// Set up backend router with CORS protection
let router = Router::with_path("hello").post(hello);
let service = Service::new(router).hoop(cors);

// Start backend server on port 5600
let acceptor = TcpListener::new("0.0.0.0:5600").bind().await;
Server::new(acceptor).serve(service).await;
}

async fn frontend_server() {
// Handler that serves the HTML page with CORS test
#[handler]
async fn index() -> Text<&'static str> {
Text::Html(HTML_DATA)
}

// Set up frontend router to serve the test page
let router = Router::new().get(index);
// Start frontend server on port 5800
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}

// HTML template with JavaScript code to test CORS
// Contains a button that triggers a POST request to the backend server
const HTML_DATA: &str = r#"
<!DOCTYPE html>
<html>
Expand Down
Loading

0 comments on commit d5d0abc

Please sign in to comment.