### Quick Start Example Source: https://github.com/salvo-rs/salvo/blob/main/crates/tus/README.md A basic example demonstrating how to integrate the TUS handler into a Salvo application with a fixed maximum upload size. ```APIDOC ## Quick Start This example shows how to set up a Salvo server with the TUS handler, including configuring a maximum upload size. ### Code Example ```rust use salvo::prelude::*; use salvo::tus::{Tus, MaxSize}; #[tokio::main] async fn main() { let tus = Tus::new() .path("/uploads") .max_size(MaxSize::Fixed(100 * 1024 * 1024)); // 100 MB limit let router = Router::new() .push(tus.into_router()); let acceptor = TcpListener::new("0.0.0.0:8698").bind().await; Server::new(acceptor).serve(router).await; } ``` ### Explanation - `Tus::new()`: Initializes a new TUS handler. - `.path("/uploads")`: Sets the base path for TUS endpoints. - `.max_size(MaxSize::Fixed(100 * 1024 * 1024))`: Configures a maximum upload size of 100 megabytes. - `tus.into_router()`: Converts the TUS handler into a Salvo router. - The rest of the code sets up the Salvo server to listen on port 8698. ``` -------------------------------- ### GET /user (with examples) Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Retrieves user information with multiple examples provided for the response. ```APIDOC ## GET /user (with examples) ### Description Retrieves user information with multiple examples provided for the response. ### Method GET ### Endpoint /user ### Response #### Success Response (200) - **User** (User) - Description of the User object #### Response Example - **Demo** (summary: "This is summary", description: "Long description") ```json { "name": "Demo" } ``` - **John** (summary: "Another user") ```json { "name": "John" } ``` ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/README.md Copies the example environment file and updates the DATABASE_URL to match your local PostgreSQL setup. This is required before running the application locally. ```bash cp .env.example .env ``` ```bash echo DATABASE_URL=postgres://darix:6775212952@localhost:5432/salvo_postgres_seaorm > .env ``` -------------------------------- ### Verify Examples Workspace Source: https://github.com/salvo-rs/salvo/blob/main/CONTRIBUTING.md When changes affect examples, navigate to the examples directory and run checks to ensure all sample applications and integration examples compile and pass tests. ```bash cd examples cargo check --all --bins --examples --tests ``` -------------------------------- ### Access Example Endpoint Source: https://github.com/salvo-rs/salvo/blob/main/examples/logging-otlp/README.md Build and run the Salvo application, then access the example endpoint to generate traces that will be sent to Jaeger. ```bash curl http://localhost:8698/ ``` -------------------------------- ### Response Example Definition Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_responses.md Illustrates how to define a response example using `json!(...)` for `serde_json::Value`. This format is used within the `examples` attribute. ```rust ("John" = (summary = "This is John", value = json!({"name": "John"}))) ``` -------------------------------- ### Basic CORS Configuration and Handler Setup Source: https://github.com/salvo-rs/salvo/blob/main/crates/cors/README.md This example demonstrates how to create a Cors handler with specific allowed origins, methods, and headers, and then apply it as a hoop to the Salvo service. It's important to add the CORS handler to the Service, not the Router, to handle preflight OPTIONS requests correctly. ```rust use salvo::cors::Cors; use salvo::http::Method; use salvo::prelude::*; #[handler] async fn hello() -> &'static str { "Hello World" } #[tokio::main] async fn main() { let cors = Cors::new() .allow_origin("https://example.com") .allow_methods([Method::GET, Method::POST]) .allow_headers("content-type") .into_handler(); let router = Router::new().get(hello); let acceptor = TcpListener::new("127.0.0.1:7878").bind().await; Server::new(acceptor) .serve(Service::new(router).hoop(cors)) .await; } ``` -------------------------------- ### Salvo TUS Quick Start Source: https://github.com/salvo-rs/salvo/blob/main/crates/tus/README.md Set up a TUS endpoint in your Salvo application with a configurable maximum upload size. This example demonstrates basic initialization and routing. ```rust use salvo::prelude::*; use salvo::tus::{Tus, MaxSize}; #[tokio::main] async fn main() { let tus = Tus::new() .path("/uploads") .max_size(MaxSize::Fixed(100 * 1024 * 1024)); // 100 MB limit let router = Router::new() .push(tus.into_router()); let acceptor = TcpListener::new("0.0.0.0:8698").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Install Salvo CLI and Create New Project Source: https://github.com/salvo-rs/salvo/blob/main/README.md Install the Salvo CLI tool using Cargo and then create a new project named 'my_project'. ```bash cargo install salvo-cli ``` ```bash salvo new my_project ``` -------------------------------- ### Response Examples Syntax Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Defines the syntax for creating response examples, including name, summary, description, value, and external_value attributes. ```APIDOC ## Response `examples(...)` syntax * `name = ...` This is first attribute and value must be literal string. * `summary = ...` Short description of example. Value must be literal string. * `description = ...` Long description of example. Attribute supports markdown for rich text representation. Value must be literal string. * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that _`serde_json::json!`_ can parse as a _`serde_json::Value`_. * `external_value = ...` Define URI to literal example value. This is mutually exclusive to the _`value`_ attribute. Value must be literal string. _**Example of example definition.**_ ```text ("John" = (summary = "This is John", value = json!({'name': 'John'}))) ``` ``` -------------------------------- ### Install SeaORM CLI Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/README.md Installs the Sea-ORM command-line tool with PostgreSQL support. Ensure Rust and Cargo are installed. ```bash cargo install sea-orm-cli ``` -------------------------------- ### Configure Environment Variables and Run Application Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-diesel/README.md Copies the example environment file and updates the DATABASE_URL. Then, runs the Salvo application using Cargo. ```bash cp .env.example .env echo DATABASE_URL=postgres://darix:6775212952@localhost:5432/salvo_postgres > .env car go run ``` -------------------------------- ### Simple Pet with descriptions and example Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_schema.md Defines a `Pet` struct with field descriptions and an object-level example using `#[salvo(schema(example = ...))]`. ```rust # use salvo_oapi::ToSchema; /// This is a pet. #[derive(ToSchema)] #[salvo(schema(example = json!({"name": "bob the cat", "id": 0})))] struct Pet { /// Unique id of a pet. id: u64, /// Name of a pet. name: String, /// Age of a pet if known. age: Option, } ``` -------------------------------- ### Response Example Definition Syntax Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Defines the structure for an example within a response, including name, summary, description, and value. The value must be a JSON literal parsable by `serde_json::json!`. ```text ("John" = (summary = "This is John", value = json!({"name": "John"}))) ``` -------------------------------- ### Define Endpoint with Multiple Response Examples Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Defines an endpoint that returns a `User` object and provides multiple distinct examples for the successful response. Each example can have its own summary and description. ```Rust # use salvo_core::prelude::* # use salvo_oapi::ToSchema; # #[derive(serde::Serialize, serde::Deserialize, ToSchema)] # struct User { # name: String # } #[salvo_oapi::endpoint( responses( (status_code = 200, body = User, examples( ("Demo" = (summary = "This is summary", description = "Long description", value = json!(User{name: "Demo".to_string()}))), ("John" = (summary = "Another user", value = json!({"name": "John"}))) ) ) ) )] async fn get_user() -> Json { Json(User {name: "John".to_string()}) } ``` -------------------------------- ### Basic OpenAPI Setup with Salvo Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/lib.md Demonstrates how to set up basic OpenAPI documentation generation for a Salvo application. It includes deriving `ToSchema` for data types, using the `#[endpoint]` macro for handlers, and mounting Swagger UI. ```rust use salvo::prelude::*; use salvo::oapi::extract::*; #[derive(ToSchema, serde::Deserialize)] struct User { id: i64, name: String, } #[endpoint] async fn get_user(id: PathParam) -> Json { Json(User { id: *id, name: "Alice".into() }) } #[tokio::main] async fn main() { let router = Router::new() .push(Router::with_path("users/").get(get_user)); let doc = OpenApi::new("My API", "1.0.0").merge_router(&router); let router = router .push(doc.into_router("/api-doc/openapi.json")) .push(SwaggerUi::new("/api-doc/openapi.json").into_router("/swagger-ui")); let acceptor = TcpListener::new("127.0.0.1:8080").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Run PostgreSQL Instance with Docker Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-diesel/README.md Starts a PostgreSQL instance in a Docker container. Configure user, password, and database name as needed. ```bash docker run -d \ --name salvo_postgres \ -e POSTGRES_USER=darix \ -e POSTGRES_PASSWORD=6775212952 \ -e POSTGRES_DB=salvo_postgres_diesel \ -p 5432:5432 \ postgres:latest ``` -------------------------------- ### Run PostgreSQL Instance with Docker Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/README.md Starts a local PostgreSQL instance using Docker. Configure environment variables for user, password, and database name as needed. ```bash docker run -d \ --name salvo_postgres \ -e POSTGRES_USER=darix \ -e POSTGRES_PASSWORD=6775212952 \ -e POSTGRES_DB=salvo_postgres_seaorm \ -p 5432:5432 \ postgres:latest ``` -------------------------------- ### Install cargo-fuzz Source: https://github.com/salvo-rs/salvo/blob/main/fuzz/README.md Installs the cargo-fuzz tool. Ensure you are using a nightly toolchain for running targets. ```bash cargo install cargo-fuzz --locked ``` -------------------------------- ### Launch OpenTelemetry Server 1 Source: https://github.com/salvo-rs/salvo/blob/main/examples/otel-jaeger/README.md Launches the first example OpenTelemetry server. Ensure this is run after the Jaeger instance is active. ```shell cargo run --bin example-otel-server1 ``` -------------------------------- ### Rust: Salvo Compression Middleware Setup Source: https://github.com/salvo-rs/salvo/blob/main/crates/compression/README.md Demonstrates how to set up and use the Compression middleware in a Salvo application. It enables Gzip compression with a default level and sets a minimum response length threshold for compression. ```rust use salvo::prelude::*; use salvo::compression::{Compression, CompressionLevel}; #[handler] async fn hello() -> &'static str { "Hello World!" } #[tokio::main] async fn main() { let compression = Compression::new() .enable_gzip(CompressionLevel::Default) .min_length(1024); // Only compress responses > 1KB let router = Router::new() .hoop(compression) .get(hello); let acceptor = TcpListener::new("0.0.0.0:8698").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Install Diesel CLI with Postgres Support Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-diesel/README.md Installs the Diesel CLI with PostgreSQL features. Requires libpq-dev for Debian/Ubuntu systems. ```bash sudo apt-get update && apt-get install -y libpq-dev cargo install diesel_cli --no-default-features --features postgres ``` -------------------------------- ### Launch OpenTelemetry Server 2 Source: https://github.com/salvo-rs/salvo/blob/main/examples/otel-jaeger/README.md Launches the second example OpenTelemetry server. This server also sends trace data to Jaeger. ```shell cargo run --bin example-otel-server2 ``` -------------------------------- ### Basic OpenAPI Endpoint and Document Generation Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/README.md This example demonstrates how to define an endpoint using `#[endpoint]`, generate an OpenAPI document from a router, and mount the document and Swagger UI router. ```rust use salvo::oapi::extract::QueryParam; use salvo::prelude::*; #[endpoint] async fn hello(name: QueryParam) -> String { format!("Hello, {}!", name.as_deref().unwrap_or("World")) } #[tokio::main] async fn main() { let router = Router::new().push(Router::with_path("hello").get(hello)); let doc = OpenApi::new("hello api", "0.1.0").merge_router(&router); let router = router .unshift(doc.into_router("/api-doc/openapi.json")) .unshift(SwaggerUi::new("/api-doc/openapi.json").into_router("/swagger-ui")); let acceptor = TcpListener::new("127.0.0.1:7878").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Run Salvo Todos API Source: https://github.com/salvo-rs/salvo/blob/main/examples/oapi-todos/README.md Execute this command in your terminal to start the Salvo Todos API server. ```bash cargo run ``` -------------------------------- ### Run Jaeger with Docker Source: https://github.com/salvo-rs/salvo/blob/main/examples/logging-otlp/README.md Start Jaeger using Docker to set up its UI and OTLP collector for receiving telemetry data. ```bash docker run -d -p 16686:16686 -p 4317:4317 -e COLLECTOR_OTLP_ENABLED=true jaegertracing/all-in-one:latest ``` -------------------------------- ### Response Links Syntax Example Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Illustrates the full syntax for defining links within a response, including operation reference, parameters, request body, and server information. ```text responses( (status = 200, description = "success response", links( ("link_name" = ( operation_id = "test_links", parameters(("key" = "value"), ("json_value" = json!(1))), request_body = "this is body", server(url = "http://localhost") )) ) ) ) ``` -------------------------------- ### Method reference for attribute values Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_schema.md Uses method references for `example` and `default` schema attributes, demonstrating dynamic value assignment. ```rust # use salvo_oapi::ToSchema; #[derive(ToSchema)] struct Pet { #[salvo(schema(example = u64::default, default = u64::default))] id: u64, #[salvo(schema(default = default_name))] name: String, age: Option, } fn default_name() -> String { "bob".to_string() } ``` -------------------------------- ### Quick Start JWT Authentication with Header Source: https://github.com/salvo-rs/salvo/blob/main/crates/jwt-auth/README.md Implement JWT authentication using HeaderFinder for the Authorization header and force_passed(true) to allow handlers to manage auth states. ```rust use salvo::jwt_auth::{ConstDecoder, HeaderFinder, JwtAuthState}; use salvo::prelude::*; use serde::{Deserialize, Serialize}; const SECRET: &[u8] = b"replace-with-a-secret-from-your-config"; #[derive(Serialize, Deserialize, Clone, Debug)] struct Claims { sub: String, exp: i64, } #[handler] async fn me(depot: &mut Depot, res: &mut Response) { match depot.jwt_auth_state() { JwtAuthState::Authorized => { let data = depot.jwt_auth_data::().unwrap(); res.render(Json(&data.claims)); } JwtAuthState::Unauthorized => res.render(StatusError::unauthorized()), JwtAuthState::Forbidden => res.render(StatusError::forbidden()), } } #[tokio::main] async fn main() { let auth = JwtAuth::::new(ConstDecoder::from_secret(SECRET)) .finders(vec![Box::new(HeaderFinder::new())]) .force_passed(true); let router = Router::new().hoop(auth).get(me); let acceptor = TcpListener::new("127.0.0.1:7878").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### GET /user Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Retrieves user information, supporting multiple content types for different user versions. ```APIDOC ## GET /user ### Description Retrieves user information, supporting multiple content types for different user versions. ### Method GET ### Endpoint /user ### Response #### Success Response (200) - **application/vnd.user.v1+json** (User1) - Example: `{"id": "id"}` - **application/vnd.user.v2+json** (User2) - Example: `{"id": 2}` ``` -------------------------------- ### Run Jaeger Docker Container Source: https://github.com/salvo-rs/salvo/blob/main/examples/otel-jaeger/README.md Starts a Jaeger all-in-one Docker container with OTLP enabled. This is the first step to sending trace data. ```shell docker run -d -e COLLECTOR_OTLP_ENABLED=true -p6831:6831/udp -p6832:6832/udp -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest ``` -------------------------------- ### Derive ToSchema with Doc Comments Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_schema.md Example of deriving ToSchema for a struct with doc comments that will be used as schema descriptions. ```rust /// This is a pet #[derive(salvo_oapi::ToSchema)] struct Pet { /// Name for your pet name: String, } ``` -------------------------------- ### Create a Response from Named Struct Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_response.md Illustrates creating a response from a named struct (`Person`) with overridden description, content type, example, and headers. ```APIDOC ## Create a response from named struct. ### Description This example demonstrates how to use `#[salvo(response(...))]` attributes on a struct (`Person`) to customize its OpenAPI documentation. It overrides the default description, sets a specific content type, provides a JSON example, and defines custom response headers. ### Method (Not explicitly defined, but implied to be part of an API endpoint) ### Endpoint (Not explicitly defined) ### Response #### Success Response (200) - **response** (`Person`) - The response body representing a person. ### Request Example (Not applicable for this example) ### Response Example ```json { "name": "the name" } ``` #### Headers - **csrf-token**: Description: "response csrf token" - **random-id**: Type: `i32` ``` -------------------------------- ### Send Request from OpenTelemetry Client Source: https://github.com/salvo-rs/salvo/blob/main/examples/otel-jaeger/README.md Executes the OpenTelemetry client example to send a request. This request will generate traces visible in Jaeger. ```shell cargo run --bin example-otel-client ``` -------------------------------- ### Using #[craft] Macro for Salvo Handlers Source: https://github.com/salvo-rs/salvo/blob/main/crates/craft-macros/README.md Demonstrates how to use the `#[craft]` macro to convert methods within an `impl` block into Salvo `Handler` implementations. This example shows different receiver types (`&self`, `Arc`, and no receiver) and how to register them with Salvo's router. ```rust use salvo::oapi::extract::* use salvo::prelude::* use salvo_craft_macros::craft use std::sync::Arc; #[tokio::main] async fn main() { let service = Arc::new(Service::new(1)); let router = Router::new() .push(Router::with_path("add1").get(service.add1())) .push(Router::with_path("add2").get(service.add2())) .push(Router::with_path("add3").get(Service::add3())); let acceptor = TcpListener::new("127.0.0.1:8698").bind().await; Server::new(acceptor).serve(router).await; } #[derive(Clone)] pub struct Service { state: i64, } #[craft] impl Service { fn new(state: i64) -> Self { Self { state } } /// doc line 1 /// doc line 2 #[craft(handler)] fn add1(&self, left: QueryParam, right: QueryParam) -> String { (self.state + *left + *right).to_string() } /// doc line 3 /// doc line 4 #[craft(handler)] pub(crate) fn add2(self: ::std::sync::Arc, left: QueryParam, right: QueryParam) -> String { (self.state + *left + *right).to_string() } /// doc line 5 /// doc line 6 #[craft(handler)] pub fn add3(left: QueryParam, right: QueryParam) -> String { (*left + *right).to_string() } } ``` -------------------------------- ### Response from Named Struct with Customizations Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_response.md Shows how to create a response from a named struct, overriding its description and content type, and adding examples and headers using `#[salvo(response(...))]` attributes. ```rust use salvo_oapi::{ToSchema, ToResponse}; /// This is description /// /// It will also be used in `ToSchema` if present #[derive(ToSchema, ToResponse)] #[salvo( response( description = "Override description for response", content_type = "text/xml" ) )] #[salvo( response( example = json!({"name": "the name"}), headers( ("csrf-token", description = "response csrf token"), ("random-id" = i32) ) ) )] struct Person { name: String, } ``` -------------------------------- ### Serde Attribute Support Example Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_schema.md Demonstrates how `#[serde(rename_all = "...")]`, `#[serde(rename = "...")]`, and `#[serde(skip)]` affect the generated OpenAPI schema. ```rust # use serde::Serialize; # use salvo_oapi::ToSchema; #[derive(Serialize, ToSchema)] struct Foo(String); #[derive(Serialize, ToSchema)] #[serde(rename_all = "camelCase")] enum Bar { UnitValue, #[serde(rename_all = "camelCase")] NamedFields { #[serde(rename = "id")] named_id: &'static str, name_list: Option> }, UnnamedFields(Foo), #[serde(skip)] SkipMe, } ``` -------------------------------- ### Define Endpoint Parameters with Tuples Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Use tuples to specify parameters for endpoints, defining name, type, location, and other attributes. This example shows various parameter types and configurations. ```rust parameters( ("limit" = i32, Query), ("x-custom-header" = String, Header, description = "Custom header"), ("id" = String, Path, deprecated, description = "Pet database id"), ("name", Path, deprecated, description = "Pet name"), ( "value" = inline(Option<[String]>), Query, description = "Value description", style = Form, allow_reserved, deprecated, explode, example = json!(["Value"])), max_length = 10, min_items = 1 ) ) ``` -------------------------------- ### Salvo Auto HTTPS with ACME Source: https://github.com/salvo-rs/salvo/blob/main/README.md Configuration for enabling automatic TLS certificate management using Let's Encrypt. This example sets up a listener for HTTPS on port 443, adds a domain, configures the HTTP-01 challenge, and enables HTTP/3 support. ```rust let listener = TcpListener::new("0.0.0.0:443") .acme() .add_domain("example.com") .http01_challenge(&mut router) .quinn("0.0.0.0:443"); // HTTP/3 support ``` -------------------------------- ### Multiple Response Content Types with `content()` Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Specifies multiple response return types for a single status code, each with its own example. This is useful for versioned content types. ```text responses( (status_code = 200, content( ("application/vnd.user.v1+json" = User, example = json!(User {id: "id".to_string()})), ("application/vnd.user.v2+json" = User2, example = json!(User2 {id: 2})) ) ) ) ``` -------------------------------- ### Integrate Salvo OpenTelemetry Middleware Source: https://github.com/salvo-rs/salvo/blob/main/crates/otel/README.md Add the `Metrics` and `Tracing` middleware to your Salvo application's router to enable OpenTelemetry collection. Ensure your OpenTelemetry provider is initialized before starting the server. ```rust use salvo::prelude::*; use salvo::otel::{Metrics, Tracing}; #[handler] async fn hello() -> &'static str { "Hello World!" } #[tokio::main] async fn main() { // Initialize your OpenTelemetry provider here... let router = Router::new() .hoop(Metrics::new()) .hoop(Tracing::new()) .get(hello); let acceptor = TcpListener::new("0.0.0.0:8698").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Build and Run Application with Docker Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-diesel/README.md Builds a Docker image for the application and runs it as a container, mapping the application port. ```bash docker build -t salvo_postgres_app . docker run -d -p 8698:8698 \ -e DATABASE_URL="postgres://darix:6775212952@localhost:5432/salvo_postgres" \ --name salvo_postgres_app \ salvo_postgres_app ``` -------------------------------- ### GET /pet_by_id Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Retrieves a pet by its ID. This operation is deprecated and marked as such in the OpenAPI spec. ```APIDOC ## GET /pet_by_id ### Description Retrieves a pet by its ID. This operation is deprecated and marked as such in the OpenAPI spec. ### Method GET ### Endpoint /pet_by_id ### Parameters #### Path Parameters - **id** (i32) - Required - Pet id ### Response #### Success Response (200) - **pet** (string) - Description of the pet found #### Response Example { "example": "{\"pet\": \"123\"}" } ``` -------------------------------- ### Install Salvo JWT Auth Feature Source: https://github.com/salvo-rs/salvo/blob/main/crates/jwt-auth/README.md Add the jwt-auth feature to your Salvo dependency in Cargo.toml. ```toml salvo = { version = "*", features = ["jwt-auth"] } ``` -------------------------------- ### Basic Salvo "Hello World" Application Source: https://github.com/salvo-rs/salvo/blob/main/README.md A minimal Salvo application that defines a simple handler and sets up a server to listen on port 7878. ```rust use salvo::prelude::*; #[handler] async fn hello() -> &'static str { "Hello World" } #[tokio::main] async fn main() { let router = Router::new().get(hello); let acceptor = TcpListener::new("127.0.0.1:7878").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Schema attribute at field level Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_schema.md Applies schema attributes like `example` and `default` directly to fields within a struct. ```rust # use salvo_oapi::ToSchema; #[derive(ToSchema)] struct Pet { #[salvo(schema(example = 1, default = 0))] id: u64, name: String, age: Option, } ``` -------------------------------- ### Run Database Migrations Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/README.md Applies all pending Sea-ORM migrations to set up the database schema. Ensure the PostgreSQL instance is running and accessible. ```bash sea-orm-cli migrate up ``` -------------------------------- ### Deploy with Docker Compose Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-diesel/README.md Builds and deploys the application and its dependencies (like PostgreSQL) using Docker Compose. ```bash docker compose up -d --build ``` -------------------------------- ### Build and Run Application with Docker Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/README.md Builds a Docker image for the application and runs it as a detached container. The DATABASE_URL environment variable must be set to connect to the PostgreSQL instance. ```bash docker build -t salvo_postgres_app . docker run -d -p 8698:8698 \ -e DATABASE_URL="postgres://darix:6775212952@localhost:5432/salvo_postgres_seaorm" \ --name salvo_postgres_app \ salvo_postgres_app ``` -------------------------------- ### Complete Response Definition Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md A more detailed response definition including status code, description, body type, content type, headers, and an example. ```text responses( (status_code = 200, description = "Success response", body = Pet, content_type = "application/json", headers(...), example = json!({"id": 1, "name": "bob the cat"}) ) ) ``` -------------------------------- ### Setting and Showing Flash Messages with CookieStore Source: https://github.com/salvo-rs/salvo/blob/main/crates/flash/README.md Demonstrates how to set a success flash message before redirecting and how to retrieve and display it on the next request using CookieStore. Ensure CookieStore is added as a hoop in your router. ```rust use salvo::prelude::*; use salvo::flash::{FlashDepotExt, CookieStore}; #[handler] async fn submit_form(depot: &mut Depot, res: &mut Response) { // Set flash message before redirect depot.outgoing_flash_mut().success("Form submitted successfully!"); res.render(Redirect::other("/result")); } #[handler] async fn show_result(depot: &mut Depot, res: &mut Response) { if let Some(flash) = depot.incoming_flash() { for msg in flash.iter() { println!("{}: {}", msg.level, msg.value); } } res.render("Result page"); } #[tokio::main] async fn main() { let router = Router::new() .hoop(CookieStore::new().into_handler()) .push(Router::with_path("submit").post(submit_form)) .push(Router::with_path("result").get(show_result)); let acceptor = TcpListener::new("0.0.0.0:8698").bind().await; Server::new(acceptor).serve(router).await; } ``` -------------------------------- ### Create enum with numeric values Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_schema.md Defines an enum with numeric values using `#[repr(u8)]` and applies schema attributes for default and example values. ```rust # use salvo_oapi::ToSchema; #[derive(ToSchema)] #[repr(u8)] #[salvo(schema(default = default_value, example = 2))] enum Mode { One = 1, Two, } fn default_value() -> u8 { 1 } ``` -------------------------------- ### Run Database Migrations Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-diesel/README.md Applies all pending database migrations using the Diesel CLI to set up the database schema. ```bash diesel migration run ``` -------------------------------- ### Basic Craft Macro Usage Source: https://github.com/salvo-rs/salvo/blob/main/crates/craft/README.md Demonstrates how to use the `#[craft]` macro to convert methods into Salvo Handlers. Note that when using `&self` as the receiver, the containing type must implement `Clone`. ```rust use salvo::oapi::extract::*; use salvo::prelude::*; use salvo_craft::craft; use std::sync::Arc; #[tokio::main] async fn main() { let service = Arc::new(Service::new(1)); let router = Router::new() .push(Router::with_path("add1").get(service.add1())) .push(Router::with_path("add2").get(service.add2())) .push(Router::with_path("add3").get(Service::add3())); let acceptor = TcpListener::new("127.0.0.1:8698").bind().await; Server::new(acceptor).serve(router).await; } #[derive(Clone)] pub struct Service { state: i64, } #[craft] impl Service { fn new(state: i64) -> Self { Self { state } } /// doc line 1 /// doc line 2 #[craft(handler)] fn add1(&self, left: QueryParam, right: QueryParam) -> String { (self.state + *left + *right).to_string() } /// doc line 3 /// doc line 4 #[craft(handler)] pub(crate) fn add2( self: ::std::sync::Arc, left: QueryParam, right: QueryParam, ) -> String { (self.state + *left + *right).to_string() } /// doc line 5 /// doc line 6 #[craft(handler)] pub fn add3(left: QueryParam, right: QueryParam) -> String { (*left + *right).to_string() } } ``` -------------------------------- ### Clone Salvo Repository Source: https://github.com/salvo-rs/salvo/blob/main/CONTRIBUTING.md Clone your fork of the Salvo repository and navigate into the workspace root. This is the initial step for setting up your development environment. ```bash git clone https://github.com//salvo.git cd salvo ``` -------------------------------- ### Enum with Content Attribute Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_response.md Enums with `#[salvo(content(...))]` on variants allow defining multiple response content types for a single response. Examples can be defined per variant. ```APIDOC ## Enum with Content Attribute ### Description Enums with `#[salvo(content(...))]` on variants allow defining multiple response content types for a single response. Examples can be defined per variant. ### Code Example ```rust #[derive(salvo_oapi::ToSchema)] struct Admin { name: String, } #[derive(salvo_oapi::ToSchema)] struct Admin2 { name: String, id: i32, } #[derive(salvo_oapi::ToResponse)] enum Person { #[salvo( response(examples(("Person1" = (value = json!({"name": "name1"}))), ("Person2" = (value = json!({"name": "name2"}))))) )] Admin(#[salvo(content("application/vnd-custom-v1+json"))] Admin), #[salvo(response(example = json!({"name": "name3", "id": 1})))] Admin2(#[salvo(content("application/vnd-custom-v2+json"))] #[salvo(schema(inline))] Admin2), } ``` ``` -------------------------------- ### Override Vec Type with Another Vec Type Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_parameters.md Overrides a `Vec` field with another `Vec` type, for example, changing `Vec` to `Vec`, using the `value_type` attribute. ```rust # use salvo_oapi::ToParameters; # #[derive(ToParameters, serde::Deserialize)] #[salvo(parameters(default_parameter_in = Query))] struct Filter { #[salvo(parameter(value_type = Vec))] id: Vec } ``` -------------------------------- ### Generate OpenAPI Documentation with Doc Comments Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Use doc comments on a decorated function to define the summary and description for an OpenAPI operation. The first line serves as the summary, and subsequent lines form the description. ```rust /// This is a summary of the operation /// /// The rest of the doc comment will be included to operation description. #[salvo_oapi::endpoint()] fn endpoint() {} ``` -------------------------------- ### Access OpenAPI JSON Documentation Source: https://github.com/salvo-rs/salvo/blob/main/examples/oapi-todos/README.md Navigate to this URL in your browser to view the OpenAPI specification for the API. ```bash http://0.0.0.0:8698/api-doc/openapi.json ``` -------------------------------- ### Salvo JSON API Handler Source: https://github.com/salvo-rs/salvo/blob/main/README.md Example of a Salvo handler that deserializes a JSON request body into a `CreateTodo` struct and returns a JSON response of a `Todo` struct. Requires the 'serde' crate with the 'derive' feature. ```rust use salvo::http::ParseError; use salvo::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] struct CreateTodo { text: String, } #[derive(Serialize)] struct Todo { id: u64, text: String, } #[handler] async fn create_todo(req: &mut Request) -> Result, ParseError> { let payload = req.parse_json::().await?; Ok(Json(Todo { id: 1, text: payload.text, })) } ``` -------------------------------- ### Define Response Header with Name, Type, and Description Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Define a response header including its name, type, and an optional description. ```rust ("x-csrf-token" = String, description = "New csrf token") ``` -------------------------------- ### Generate New Migration File Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/migration/README.md Use this command to create a new migration file with a specified name. ```sh cargo run -- generate MIGRATION_NAME ``` -------------------------------- ### Salvo Middleware as Handler Source: https://github.com/salvo-rs/salvo/blob/main/README.md Demonstrates how middleware in Salvo is implemented as a handler, shown here by adding a Server header to the response. ```rust #[handler] async fn add_header(res: &mut Response) { res.headers_mut().insert(header::SERVER, HeaderValue::from_static("Salvo")); } Router::new().hoop(add_header).get(hello) ``` -------------------------------- ### Run Salvo Application Source: https://github.com/salvo-rs/salvo/blob/main/README.md Command to compile and run the Salvo application. ```bash cargo run ``` -------------------------------- ### Derive ToResponse for Enum with Content Variants Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_response.md Decorate an enum with `#[derive(ToResponse)]` where variants use `#[salvo(content(...))]` to define multiple response content schemas. Each variant can specify its content type and optionally use `#[salvo(schema(inline))]` to inline its schema. Examples can be defined per variant. ```rust # #[derive(salvo_oapi::ToSchema)] # struct Admin { # name: String, # } # #[derive(salvo_oapi::ToSchema)] # struct Admin2 { # name: String, # id: i32, # } #[derive(salvo_oapi::ToResponse)] enum Person { #[salvo( response(examples(("Person1" = (value = json!({"name": "name1"}))), ("Person2" = (value = json!({"name": "name2"}))))) )] Admin(#[salvo(content("application/vnd-custom-v1+json"))] Admin), #[salvo(response(example = json!({"name": "name3", "id": 1})))] Admin2(#[salvo(content("application/vnd-custom-v2+json"))] #[salvo(schema(inline))] Admin2), } ``` -------------------------------- ### Lifecycle Hooks Source: https://github.com/salvo-rs/salvo/blob/main/crates/tus/README.md Demonstrates how to use lifecycle hooks to react to TUS upload events such as creation and completion. ```APIDOC ## Lifecycle Hooks Salvo TUS allows you to hook into the upload lifecycle to perform custom actions. ### `with_on_upload_create` **Description**: Registers a callback function to be executed when a new upload is created. **Parameters**: Takes a closure that accepts `req` (request) and `upload_info` and returns a future. ### `with_on_upload_finish` **Description**: Registers a callback function to be executed when an upload is successfully finished. **Parameters**: Takes a closure that accepts `req` (request) and `upload_info` and returns a future. ### Code Example ```rust let tus = Tus::new() .with_on_upload_create(|req, upload_info| async move { println!("New upload: {:?}", upload_info); Ok(UploadPatch::default()) }) .with_on_upload_finish(|req, upload_info| async move { println!("Upload complete: {:?}", upload_info); Ok(UploadFinishPatch::default()) }); ``` ``` -------------------------------- ### Apply All Pending Migrations Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/migration/README.md Executes all pending database migrations. This is the default behavior when no specific command is provided. ```sh cargo run ``` ```sh cargo run -- up ``` -------------------------------- ### ToParameters with Serde Attributes and Inline Schema Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/derive_to_parameters.md Demonstrates using the `#[salvo(parameters(...))]` container attribute with `ToParameters` and `ToSchema` derives, incorporating Serde's `rename_all` and inline schema definition for query parameters. ```rust use serde::Deserialize; use salvo_core::prelude::*; use salvo_oapi::{ToParameters, ToSchema}; #[derive(Deserialize, ToSchema)] #[serde(rename_all = "snake_case")] enum PetKind { Dog, Cat, } #[derive(Deserialize, ToParameters)] struct PetQuery { /// Name of pet name: Option, /// Age of pet age: Option, /// Kind of pet #[salvo(parameter(inline))] kind: PetKind } #[salvo_oapi::endpoint( parameters(PetQuery), responses = ( (status_code = 200, description = "success response") ) )] async fn get_pet(query: PetQuery) { // ... } ``` -------------------------------- ### Configure Audience Validation with OidcDecoder (Multiple Audiences) Source: https://github.com/salvo-rs/salvo/blob/main/crates/jwt-auth/README.md Configure an OidcDecoder to accept multiple audiences by using the builder pattern. ```rust let decoder = OidcDecoder::builder("https://issuer.example.com") .audiences(["api://salvo-service", "api://salvo-admin"]) .build() .await?; ``` -------------------------------- ### Create a New Salvo Project Source: https://github.com/salvo-rs/salvo/blob/main/README.md Use cargo to create a new Rust project and add Salvo and Tokio as dependencies, enabling the 'oapi' feature for OpenAPI support. ```bash cargo new hello-salvo cd hello-salvo cargo add salvo tokio --features salvo/oapi,tokio/macros ``` -------------------------------- ### Fresh Migrations Source: https://github.com/salvo-rs/salvo/blob/main/examples/db-postgres-sea-orm/migration/README.md Drops all existing tables from the database and then reapplies all migrations. Use with caution as it will delete all data. ```sh cargo run -- fresh ``` -------------------------------- ### Define Response Header with Name Source: https://github.com/salvo-rs/salvo/blob/main/crates/oapi/docs/endpoint.md Define a response header with its name. ```rust ("x-csrf-token") ``` -------------------------------- ### Configure Audience Validation with OidcDecoder (Single Audience) Source: https://github.com/salvo-rs/salvo/blob/main/crates/jwt-auth/README.md Initialize an OidcDecoder for OpenID Connect tokens, specifying the issuer URL and a single expected audience. ```rust use salvo::jwt_auth::OidcDecoder; let decoder = OidcDecoder::new( "https://issuer.example.com", "api://salvo-service", ).await?; ``` -------------------------------- ### Run Local Checks Source: https://github.com/salvo-rs/salvo/blob/main/CONTRIBUTING.md Execute these commands to ensure your code adheres to project standards and passes basic checks before submitting a pull request. This includes formatting, compilation, and tests. ```bash cargo +nightly fmt --all -- --check ``` ```bash cargo check --all --bins --examples --tests ``` ```bash cargo test --all --all-features --no-fail-fast ``` ```bash cargo test --workspace --doc ```