### Basic Domain Guard Setup Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/domain_guards.md This example demonstrates the fundamental setup of domain guards, partitioning routes for different domains within a Pavex application. ```rust use pavex::blueprint::{Blueprint, Route}; use pavex::router::Redirect; let mut blueprint = Blueprint::new(); // Routes for pavex.dev blueprint.route(Route::get("/about").to(about_page)); // Routes for api.pavex.dev blueprint.route(Route::get("/users").to(list_users)); // Routes for www.pavex.dev blueprint.route(Route::get("/home").to(home_page)); ``` -------------------------------- ### Verify Pavex Setup Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/index.md Run this command to check if all Pavex dependencies are correctly installed and configured on your system. This is a useful first step for troubleshooting setup issues. ```bash pavex self setup ``` -------------------------------- ### Install Dependencies with uv Source: https://github.com/lukemathwalker/pavex/blob/main/docs/README.md Installs project dependencies using the `uv` tool. Ensure `uv` is installed before running. ```bash uv sync ``` -------------------------------- ### Install Pavex Documentation Tool Source: https://github.com/lukemathwalker/pavex/blob/main/CONTRIBUTING.md Install the `pxh` binary, used for extracting and managing code snippets in the documentation. ```bash cargo install --path docs/tools/pxh ``` -------------------------------- ### Install Pavex CLI Source: https://github.com/lukemathwalker/pavex/blob/main/CONTRIBUTING.md Install the `pavexc` binary to ensure local changes are picked up by documentation generation tools. ```bash cargo install -p pavexc_cli ``` -------------------------------- ### Install sqlx CLI Source: https://github.com/lukemathwalker/pavex/blob/main/examples/realworld/README.md Installs the sqlx CLI with specific features for native TLS and PostgreSQL support, and a version constraint. ```bash cargo install sqlx-cli \ --no-default-features \ --features native-tls,postgres \ --version 0.8.0 ``` -------------------------------- ### Create a new Pavex project Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/index.md Scaffolds a new Pavex project using the 'quickstart' template and navigates into the project directory. ```bash pavex new --template="quickstart" demo && cd demo ``` -------------------------------- ### Define GET Route Handler Source: https://context7.com/lukemathwalker/pavex/llms.txt Example of a route handler for GET requests. It takes parameters (commented out) and returns a `Response`. ```rust use pavex::Response; #[get(path = "/users/{id}")] pub async fn get_user(/* inject params here */) -> Response { Response::ok().set_typed_body("user data") } ``` -------------------------------- ### Serve Documentation Locally Source: https://github.com/lukemathwalker/pavex/blob/main/docs/README.md Starts a local development server for previewing the documentation. The server will automatically reload on changes. Access the docs at http://localhost:8000. ```bash uv run mkdocs serve --open ``` -------------------------------- ### Catch-all Domain Parameter Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/domain_guards.md This example shows how to use a catch-all domain parameter '{*any}' to match the rest of the domain, including subdomains with multiple labels. ```rust use pavex::blueprint::{Blueprint, Route}; let mut blueprint = Blueprint::new(); blueprint.domain("{*any}.example.dev").route(Route::get("/resource").to(get_resource)); ``` -------------------------------- ### Invalid Config Key: Starts with a Number Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/blueprint/config/invalid_config_keys/expectations/stderr.txt Configuration keys must begin with a letter. This example shows an error where the key starts with '2numbersfirst'. ```rust #[derive(Clone)] #[pavex::config(key = "2numbersfirst", id = "A_")] pub struct A; ``` -------------------------------- ### Example `ApplicationConfig` Structure Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/configuration/application_config.md This snapshot shows the generated `ApplicationConfig` struct, which includes fields for each configuration entry defined in the application. ```rust pub struct ApplicationConfig { pub port: u16, pub hostname: String, pub log_level: LogLevel, pub database: DatabaseConfig, pub api_keys: Vec, } ``` -------------------------------- ### Install Pavex CLI using PowerShell Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/index.md Use this command to download and execute the Pavex installation script via PowerShell. ```powershell powershell -c "irm https://pavex.dev/install.ps1 | iex" ``` -------------------------------- ### Bare Ping Test Example Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/project_structure/server.md An example of a black-box API integration test. It sends an HTTP GET request to the `/ping` endpoint and asserts that the response status code is 200 OK. ```rust use reqwest::StatusCode; #[tokio::test] async fn bare_ping_test() { let response = reqwest::get("http://localhost:8080/ping").await.unwrap(); assert_eq!(response.status(), StatusCode::OK); } ``` -------------------------------- ### Start Redis Database with Docker Compose Source: https://github.com/lukemathwalker/pavex/blob/main/runtime/sessions/pavex_session_redis/CONTRIBUTING.md Use this command to start the Redis database in detached mode for integration tests. ```sh docker compose up -d ``` -------------------------------- ### Install Pavex CLI using curl Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/index.md Use this command to download and execute the Pavex installation script via curl. ```bash curl --proto '=https' --tlsv1.2 -LsSf https://pavex.dev/install.sh | sh ``` -------------------------------- ### Constructor Registration Example Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/borrow_checker/control_flow/multiple_consumers_pass_takes_control_flow_into_account_for_errors/expectations/stderr.txt This snippet shows how a constructor for a type `B` is registered. The borrow checker identifies this as a point where `app::B` is consumed. ```rust #[pavex::request_scoped(id = "B_")] pub fn b() -> B { todo!() } ``` -------------------------------- ### Dynamic Domain Guard with Parameter Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/domain_guards.md This example illustrates dynamic domain guards using a domain parameter '{sub}'. The parameter captures parts of the domain before '.pavex.dev'. ```rust use pavex::blueprint::{Blueprint, Route}; let mut blueprint = Blueprint::new(); blueprint.domain("{sub}.pavex.dev").route(Route::get("/users").to(list_users)); ``` -------------------------------- ### Server Entrypoint in `main` function Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/project_structure/server.md This is the typical structure of the `main` function in the server crate. It initializes tracing, loads configuration, builds the application state, and starts the Pavex server. ```rust use std::net::SocketAddr; use "pavex_runtime"::telemetry::TracingConfig; use "pavex_runtime"::telemetry::TracingSubscriber; use "pavex_server"::ApplicationState; #[tokio::main] async fn main() -> anyhow::Result<()> { let tracing_config = TracingConfig::load_from_env("APP_LOG").expect("Failed to load tracing config"); let tracing_subscriber = TracingSubscriber::new(tracing_config); tracing_subscriber.init(); let configuration = Configuration::load_from_env().expect("Failed to load configuration"); let application_state = ApplicationState::new(configuration).await; let socket_addr: SocketAddr = "0.0.0.0:8080".parse().expect("Failed to parse socket address"); pavex_server::run(application_state, socket_addr).await; Ok(()) } ``` -------------------------------- ### Define POST Route Handler Source: https://context7.com/lukemathwalker/pavex/llms.txt Example of a route handler for POST requests that returns a `Response` indicating resource creation. ```rust use pavex::Response; #[post(path = "/users")] pub async fn create_user() -> Response { Response::created().set_typed_body("new user") } ``` -------------------------------- ### Raw Path Parameters Example Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/request_data/path/raw_path_parameters.md This snapshot demonstrates the behavior of `RawPathParams`. It shows how percent-encoded characters like '%20' are preserved as raw values and not automatically decoded into spaces. ```text assert_eq!(raw_path_params.get("address_id"), Some("123%20456")); assert_eq!(raw_path_params.get("home_id"), Some("789")); ``` -------------------------------- ### Define a Pre-processing Middleware Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/pre_processing.md Use the `#[pre_process]` attribute to define a new pre-processing middleware. This example shows a middleware that redirects to a normalized URL. ```rust use pavex::prelude::*; #[pre_process] fn redirect_to_normalized( ) -> Processing { // ... Processing::Continue } ``` -------------------------------- ### Constructor Example Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/borrow_checker/control_flow/multiple_consumers_pass_takes_control_flow_into_account_for_errors/expectations/stderr.txt This snippet shows another constructor that consumes `app::B` by value. This contributes to the borrow checker error when multiple components require ownership of `app::B`. ```rust #[pavex::request_scoped(id = "C_")] pub fn c(_a: A, _b: B) -> C { todo!() } ``` -------------------------------- ### Invalid Config Key: Empty Key Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/blueprint/config/invalid_config_keys/expectations/stderr.txt Configuration keys cannot be empty. This example demonstrates an error with an empty string as the key. ```rust #[derive(Clone)] #[pavex::config(key = "", id = "B_")] pub struct B; ``` -------------------------------- ### Registering Individual Routes Source: https://context7.com/lukemathwalker/pavex/llms.txt Demonstrates how to register individual HTTP routes using `Blueprint::route` with various HTTP method attributes like `#[get]`, `#[post]`, `#[put]`, `#[delete]`, and the generic `#[route]` attribute for custom methods or multiple methods. ```APIDOC ## `Blueprint::route` — Register HTTP routes Individual routes are registered with `bp.route(CONSTANT)` where `CONSTANT` is generated by `#[get]`, `#[post]`, `#[put]`, `#[patch]`, `#[delete]`, `#[head]`, `#[options]`, or the generic `#[route]` attribute. ### Example Usage ```rust use pavex::{Blueprint, get, post, put, delete, route, Response}; // Standard method shorthands #[get(path = "/articles/{id}")] pub async fn get_article() -> Response { Response::ok() } #[post(path = "/articles")] pub async fn create_article() -> Response { Response::created() } #[put(path = "/articles/{id}")] pub async fn replace_article() -> Response { Response::ok() } #[delete(path = "/articles/{id}")] pub async fn delete_article() -> Response { Response::no_content() } // Match multiple methods with the generic #[route] attribute #[route(method = ["GET", "HEAD"], path = "/healthz")] pub async fn healthz() -> Response { Response::ok() } // Non-standard methods #[route(method = "QUERY", path = "/articles", allow(non_standard_methods))] pub async fn query_articles() -> Response { Response::ok() } // Catch-all route for any HTTP method #[route(path = "/webhook", allow(any_method))] pub async fn webhook() -> Response { Response::ok() } pub fn routes_blueprint() -> Blueprint { let mut bp = Blueprint::new(); // Register routes one by one bp.route(GET_ARTICLE); bp.route(CREATE_ARTICLE); bp.route(REPLACE_ARTICLE); bp.route(DELETE_ARTICLE); bp.route(HEALTHZ); bp.route(QUERY_ARTICLES); bp.route(WEBHOOK); bp } ``` ### Parameters - `route`: A constant generated by an HTTP method attribute (e.g., `GET_ARTICLE`). ### Response - Returns a `Blueprint` instance with the route registered. ``` -------------------------------- ### Fallback Route for Unmatched Domains Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/domain_guards.md This example configures a top-level fallback route that is invoked when no other domain guards match the incoming request's domain. ```rust use pavex::blueprint::{Blueprint, Route}; use pavex::router::Redirect; let mut blueprint = Blueprint::new(); // ... other routes with domain guards ... // Fallback route for unmatched domains blueprint.fallback(Redirect::to_not_found()); ``` -------------------------------- ### Add Integration Test Module Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/testing.md This code defines a new module for integration tests, setting up the necessary structure for testing the `GET /api/greet/{name}` endpoint. ```rust mod greet_test { use pavex_quickstart::TestApi; #[derive(Debug, serde::Deserialize)] struct GreetResponse { message: String, } #[derive(Debug, serde::Deserialize)] struct ErrorResponse { error: String, } #[derive(Debug, serde::Serialize)] struct GreetRequest { name: String, } #[derive(Debug, serde::Serialize)] struct GreetRequestWithUserAgent { name: String, user_agent: String, } } ``` -------------------------------- ### Injecting RequestHead into User Constructor Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/dependency_injection/constructors.md This example shows how a User constructor can inject a `&RequestHead` to extract data from the incoming request. This demonstrates the recursive nature of dependency injection. ```rust struct User { id: u64, } impl User { fn extract(request_head: &RequestHead) -> User { // ... extract user id from Authorization header User { id: 123 } } } struct RequestHead { // ... fields representing request metadata } ``` -------------------------------- ### Run Pavex Application Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/pavexc_cli/template/README.md Use `cargo px run` to launch your Pavex application. It will start listening on port 8000 using the `dev` profile. ```bash cargo px run ``` -------------------------------- ### Configure JWT Keys in YAML Source: https://github.com/lukemathwalker/pavex/blob/main/examples/realworld/README.md Example of how to embed the generated PEM-encoded private and public keys into the application's configuration file for local development. ```yaml # [...] auth: eddsa_private_key_pem: | -----BEGIN PRIVATE KEY----- # Paste the contents of private.pem here -----END PRIVATE KEY----- eddsa_public_key_pem: | -----BEGIN PUBLIC KEY----- # Paste the contents of public.pem here -----END PUBLIC KEY----- ``` -------------------------------- ### Define Landing Page Route with #[pavex::get] Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/attributes/index.md Use the #[pavex::get] attribute to define a new route for a specific URL path. This example shows its application for the landing page. ```rust use pavex::router::get; #[get("/")] fn landing_page() -> impl IntoResponse { "Hello, world!" } ``` -------------------------------- ### Pavex Server SDK Generation Example Source: https://github.com/lukemathwalker/pavex/blob/main/ARCHITECTURE.md Illustrates the generated Rust code for a Pavex server, including routing, state management, and request handling logic. This code is automatically generated based on the application's structure and handler functions. ```rust use pavex::routing::Router; use pavex::hyper::server::{Builder, conn::AddrIncoming}; use pavex::request::RequestHead; use pavex::response::Response; struct ServerState { router: Router, application_state: ApplicationState, } pub struct ApplicationState { s0: app::HttpClient, } /// The entrypoint to build the application state, a pre-requisite to launching the web server. pub fn build_application_state(v0: app::Config) -> crate::ApplicationState { // [...] } /// The entrypoint to launch the web server. pub async fn run( server_builder: Builder, application_state: ApplicationState, ) -> Result<(), anyhow::Error> { // [...] } fn route_request( request: &RequestHead, server_state: std::sync::Arc, ) -> Response { let route_id = server_state .router .at(request.uri().path()) .expect("Failed to match incoming request path"); match route_id.value { 0u32 => route_handler_0(server_state.application_state.s0.clone(), request), _ => panic!("This is a bug, no route registered for a route id"), } } pub fn route_handler_0( v0: app::HttpClient, v1: RequestHead, ) -> Response { let v2 = app::extract_path(v1); let v3 = app::logger(); app::stream_file(v2, v3, v0) } ``` -------------------------------- ### Initialize Database Source: https://github.com/lukemathwalker/pavex/blob/main/examples/realworld/README.md Initializes the local Postgres instance and applies SQL migrations using a provided script. ```bash ./scripts/init_db.sh ``` -------------------------------- ### Request Handler Example Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/borrow_checker/control_flow/multiple_consumers_pass_takes_control_flow_into_account_for_errors/expectations/stderr.txt This snippet demonstrates a request handler that consumes `app::B` by value. The borrow checker flags this as a conflict when another component also consumes `app::B`. ```rust #[pavex::get(path = "/home")] pub fn handler(_b: B, _c: C) -> Response { todo!() } ``` -------------------------------- ### Middleware Applied After Route Registration Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/scoping.md This example demonstrates that a middleware registered after a route handler does not affect that handler. The `WRAP_2` middleware is registered after the `GET /` route, so it does not apply. ```rust let app = App::new() .at(வதற்காக("/", get(handler))) .wrap(WRAP_2); assert_eq!(app.get_handler_by_path("/").unwrap().get_middleware_stack().len(), 0); ``` -------------------------------- ### Registering Individual HTTP Routes with Blueprint Source: https://context7.com/lukemathwalker/pavex/llms.txt Use `bp.route(CONSTANT)` to register individual routes, where `CONSTANT` is generated by route attributes like `#[get]`, `#[post]`, etc. Ensure the correct attribute and path are used. ```rust use pavex::Blueprint; use pavex::request::path::PathParams; // Standard method shorthands #[get(path = "/articles/{id}")] pub async fn get_article() -> Response { Response::ok() } #[post(path = "/articles")] pub async fn create_article() -> Response { Response::created() } #[put(path = "/articles/{id}")] pub async fn replace_article() -> Response { Response::ok() } #[delete(path = "/articles/{id}")] pub async fn delete_article() -> Response { Response::no_content() } // Match multiple methods with the generic #[route] attribute #[route(method = ["GET", "HEAD"], path = "/healthz")] pub async fn healthz() -> Response { Response::ok() } // Non-standard methods #[route(method = "QUERY", path = "/articles", allow(non_standard_methods))] pub async fn query_articles() -> Response { Response::ok() } // Catch-all route for any HTTP method #[route(path = "/webhook", allow(any_method))] pub async fn webhook() -> Response { Response::ok() } pub fn routes_blueprint() -> Blueprint { let mut bp = Blueprint::new(); // Register routes one by one bp.route(GET_ARTICLE); bp.route(CREATE_ARTICLE); // Or in bulk – equivalent to registering every annotated function in the module bp.routes(from![crate::articles]); bp } ``` -------------------------------- ### Greet Endpoint Happy Path Test Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/testing.md This test verifies the happy path for the `GET /api/greet/{name}` endpoint. It spawns the application, sends a request with a name and a User-Agent header, and asserts the expected greeting message. ```rust #[test] fn greet_happy_path() { let api = TestApi::spawn(None); let request = GreetRequestWithUserAgent { name: "World".to_string(), user_agent: "TestClient".to_string() }; let response = api.post_greet(request).expect_success(); let greet_response: GreetResponse = response.json().unwrap(); assert_eq!(greet_response.message, "Hello World!"); } ``` -------------------------------- ### Middleware Applied After Blueprint Nesting Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/scoping.md This example shows that a middleware registered after a Blueprint is nested applies to routes within that Blueprint. The `WRAP_2` middleware is registered after the nested Blueprint, so it applies to the `GET /` route within it. ```rust let app = App::new() .nest(வதற்காக("/nested"), Blueprint::new().at(வதற்காக("/", get(handler)))) .wrap(WRAP_2); assert_eq!(app.get_handler_by_path("/nested/").unwrap().get_middleware_stack().len(), 1); ``` -------------------------------- ### Pavex Router: Route Path Must Start with Slash Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/blueprint/router/route_path_is_validated/expectations/stderr.txt When defining a route path in Pavex, non-empty paths must begin with a forward slash (/). This example shows an error where the path 'api' is used instead of '/api'. ```rust #[pavex::get(path = "api")] pub fn missing_leading_slash() -> String { // ... } ``` -------------------------------- ### Cargo.toml Configuration for `cargo-px` Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/project_structure/app.md This `Cargo.toml` section configures `cargo-px` to generate the `server_sdk` crate by executing a binary named `bp` from the current workspace. ```toml [package] name = "server_sdk" version = "0.1.0" edition = "2021" [dependencies] pavex_runtime = "0.3.0" [package.metadata.pavex] # This tells cargo-px to generate the whole crate by executing # a binary called `bp` from the current Cargo workspace. # # The binary is defined in the `demo` crate: # https://github.com/LukeMathWalker/pavex/blob/0.3.0/demo/Cargo.toml#L27 build = "bp" ``` -------------------------------- ### Route Organization with `prefix`, `domain`, and `nest` Source: https://context7.com/lukemathwalker/pavex/llms.txt Explains how to organize routes hierarchically using `Blueprint::prefix` to prepend path segments, `Blueprint::domain` to restrict routes to a specific host, and `Blueprint::nest` to insert child blueprints. ```APIDOC ## `Blueprint::prefix` / `Blueprint::domain` / `Blueprint::nest` — Route organization Blueprints can be composed hierarchically. `prefix` prepends a path segment, `domain` restricts routes to a specific `Host` header value, and `nest` inserts a child blueprint. ### Example Usage ```rust use pavex::{Blueprint, blueprint::from, get, Response}; #[get(path = "/users")] pub fn list_users() -> Response { Response::ok() } #[get(path = "/posts")] pub fn list_posts() -> Response { Response::ok() } #[get(path = "/metrics")] pub fn metrics() -> Response { Response::ok() } fn api_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate::api]); bp.routes(from![crate::api]); bp } fn admin_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate::admin]); // GET /metrics → only accessible via admin.example.com bp.route(METRICS); bp } pub fn root_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate, pavex]); // All routes from api_blueprint get a /v1 prefix bp.prefix("/v1").nest(api_blueprint()); // Admin routes restricted to admin subdomain with /admin prefix bp.prefix("/admin").domain("admin.example.com").nest(admin_blueprint()); bp } // Resulting routes: // GET /v1/users → list_users // GET /v1/posts → list_posts // GET /admin/metrics → metrics (only for Host: admin.example.com) ``` ### Methods - `prefix(path_segment: &str)`: Prepends a path segment to all routes within the blueprint. - `domain(host: &str)`: Restricts the blueprint's routes to a specific host. - `nest(child_blueprint: Blueprint)`: Inserts a child blueprint into the current blueprint. ### Inheritance Constructors registered on a parent blueprint are inherited by all nested blueprints. Constructors registered on a child blueprint are private to it. ``` -------------------------------- ### Retrieve data from a session Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/sessions/data.md Use `get` to retrieve a value from the session state. It returns an `Option` and requires a type annotation for deserialization. `get` does not modify the session state. ```rust use pavex::session::Session; async fn handler(session: &Session) -> Option { session.get("user.id").await } ``` -------------------------------- ### Register configuration entries in bulk using import Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/configuration/entries.md Register all configuration entries defined in the current crate by using a wildcard import. This is a convenient way to include all defined configuration entries. ```rust use my_app::configuration::*; let mut blueprint = Blueprint::new(); blueprint.import(configuration::*); ``` -------------------------------- ### Regenerate All Documentation Snippets Source: https://github.com/lukemathwalker/pavex/blob/main/CONTRIBUTING.md Regenerate all code snippets used in the documentation. Navigate to the `docs/examples` directory before running. ```bash cd docs/examples pxh example regenerate ``` -------------------------------- ### Rust Import Path Error Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/reflection/crate_resolution/transitive_dependencies_can_be_renamed/expectations/stderr.txt This error occurs when an import path is not fully qualified. Ensure local imports start with `crate::` and dependency imports start with the dependency name. ```rust ERROR:\n × `new_logger` is not a fully-qualified import path.\n │\n │ ╭─[src/lib.rs:9:1]\n │  9 │ let mut bp = Blueprint::new();\n │ 10 │ bp.constructor(f!(new_logger), Lifecycle::Singleton);\n │ ·  ───────┬──────\n │ · ╰── The relative import path was registered here\n │ 11 │ bp.route(GET, "/home", f!(crate::handler));\n │ ╰────\n │  help: If it is a local import, the path must start with `crate::`.\n │ If it is an import from a dependency, the path must start with the\n │ dependency name (e.g. `dependency::`). ``` -------------------------------- ### Build the Pavex Application Source: https://github.com/lukemathwalker/pavex/blob/main/examples/realworld/README.md Builds the Pavex application. Add the `--release` flag for maximum performance. ```bash # Add --release if you're looking for maximum performance cargo px build ``` -------------------------------- ### Define a GET Route with Pavex Attribute Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/routing.md Use the `#[pavex::get]` attribute to define a route that responds to GET requests for a specific path. This is the primary way to declare your API endpoints. ```rust use pavex::get; #[get("/ping")] fn ping() -> impl IntoResponse { Response::ok().set_typed_body("pong") } ``` -------------------------------- ### Conflicting GET / Route Handlers Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/blueprint/router/conflicting_any_and_single_method_guards/expectations/stderr.txt Pavex detects and reports an error when two different request handlers are registered for the same path (`/`) and method (implicitly `GET` for the second handler, and `any_method` for the first). This typically occurs when using `#[pavex::route(allow(any_method))]` alongside a specific method attribute like `#[pavex::get]`. To resolve this, remove all but one of the conflicting handlers. ```rust #[pavex::route(path = "/", allow(any_method))] pub fn any_root() -> Response { todo!() } ``` ```rust #[pavex::get(path = "/")] pub fn get_root() -> Response { todo!() } ``` -------------------------------- ### Error: Missing UserAgent Constructor Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/dependency_injection.md Example of a Pavex build error when a required constructor for an input type is missing. ```ansi-color error[E0599]: no method named `new` found for struct `pavex::request::UserAgent` in the current scope --> src/main.rs:10:30 | 10 | let user_agent = pavex::request::UserAgent::new(); | ^^^^^^^^^^^^^^^^^^ method not found in `pavex::request::UserAgent` ``` -------------------------------- ### Post-processing Middleware that can Fail Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/post_processing.md Post-processing middlewares can return a `Result`. This example shows a `compress` middleware that might fail during compression. ```rust use pavex::response::Response; use std::io::Result; #[pavex::post_process] fn compress(response: &mut Response) -> Result<()> { // ... compression logic ... Ok(()) } ``` -------------------------------- ### Registering Routes in Bulk Source: https://context7.com/lukemathwalker/pavex/llms.txt Shows how to register all annotated routes within a specified module using `Blueprint::routes` and `pavex::blueprint::from!`. This is a convenient way to add multiple routes at once. ```APIDOC ## `Blueprint::routes` — Register HTTP routes from a module `bp.routes(from![...])` registers all annotated routes discovered in the given module sources at once. ### Example Usage ```rust use pavex::{Blueprint, blueprint::from}; // Assuming `crate::articles` contains functions annotated with HTTP method attributes. pub fn routes_blueprint() -> Blueprint { let mut bp = Blueprint::new(); // Register all annotated routes from the `crate::articles` module bp.routes(from![crate::articles]); bp } ``` ### Parameters - `from![...]`: A macro that specifies the module(s) to discover routes from. ### Response - Returns a `Blueprint` instance with all discovered routes registered. ``` -------------------------------- ### Define API Structure with Blueprint Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/project_structure/app.md Use `Blueprint::new()` to initialize the API structure. This is where you declare routes, middlewares, constructors, and error handlers. ```rust use pavex::blueprint::Blueprint; #[tokio::main] async fn main() { let mut app = Blueprint::new(); // Define your API structure here // ... add routes, middlewares, etc. app.build().await; } ``` -------------------------------- ### Building a Pavex Blueprint with Wrapping Middlewares Source: https://context7.com/lukemathwalker/pavex/llms.txt Construct a Pavex Blueprint, importing necessary modules, applying global wrapping middlewares like `apply_timeout`, and conditionally applying others like `require_auth` to specific route prefixes. ```rust use pavex::{Blueprint, blueprint::from, wrap, middleware::Next, Response}; use tokio::time::{timeout, Duration}; use pavex::{methods, request_scoped, request::RequestHead}; // ── Timeout middleware ──────────────────────────────────────────────────────── #[wrap] pub async fn apply_timeout(next: Next) -> Response where C: std::future::IntoFuture, { timeout(Duration::from_secs(30), next.into_future()) .await .unwrap_or_else(|_| Response::service_unavailable() .set_typed_body("Request timed out") ) } // ── Authentication middleware that injects a constructed type ───────────────── pub struct AuthenticatedUser { pub id: u64 } #[methods] impl AuthenticatedUser { #[request_scoped] pub fn from_request(head: &RequestHead) -> Result { // validate token from Authorization header Ok(Self { id: 42 }) } } pub struct AuthError; #[wrap] pub async fn require_auth( _user: &AuthenticatedUser, // Pavex injects this; returns 4xx if construction fails next: Next, ) -> Response where C: std::future::IntoFuture, { next.await } pub fn build_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate, pavex]); bp.wrap(APPLY_TIMEOUT); // apply_auth only to /private routes bp.prefix("/private").nest({ let mut child = Blueprint::new(); child.wrap(REQUIRE_AUTH); child.routes(from![crate::private]); child }); bp } ``` -------------------------------- ### Static Domain Guard Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/domain_guards.md A static domain guard matches a single, predetermined domain. This example shows how to configure a guard for 'pavex.dev'. ```rust use pavex::blueprint::{Blueprint, Route}; let mut blueprint = Blueprint::new(); blueprint.domain("pavex.dev").route(Route::get("/about").to(about_page)); ``` -------------------------------- ### Pavex application log output Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/index.md Example of JSON log output from a running Pavex application, indicating it's listening for requests. ```json { "name": "demo", "msg": "Starting to listen for incoming requests at 127.0.0.1:8000", "level": 30, "target": "api" // [...] } ``` -------------------------------- ### Pre- and post-processing middleware order (no early return) Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/execution_order.md Pre-processing middlewares execute before the request handler, and post-processing middlewares execute after. Within each category, middlewares execute in registration order. Pre-processing always precedes post-processing. ```rust use pavex::middleware::{Middleware, Processing, Next, MiddlewareConstructor}; use std::future::Future; struct PreMiddleware1; impl MiddlewareConstructor for PreMiddleware1 { type Middleware = Self; fn new() -> Self { Self } } impl Middleware for PreMiddleware1 { type Input = (); type Output = (); fn call<'a, 'b>(&'a self, _input: Self::Input, next: Next<'b>) -> impl Future + 'a { async move { println!("PRE_1"); next.await } } } struct PreMiddleware2; impl MiddlewareConstructor for PreMiddleware2 { type Middleware = Self; fn new() -> Self { Self } } impl Middleware for PreMiddleware2 { type Input = (); type Output = (); fn call<'a, 'b>(&'a self, _input: Self::Input, next: Next<'b>) -> impl Future + 'a { async move { println!("PRE_2"); next.await } } } struct GetIndex; impl MiddlewareConstructor for GetIndex { type Middleware = Self; fn new() -> Self { Self } } impl Middleware for GetIndex { type Input = (); type Output = (); fn call<'a, 'b>(&'a self, _input: Self::Input, next: Next<'b>) -> impl Future + 'a { async move { println!("GET_INDEX"); next.await } } } struct PostMiddleware1; impl MiddlewareConstructor for PostMiddleware1 { type Middleware = Self; fn new() -> Self { Self } } impl Middleware for PostMiddleware1 { type Input = (); type Output = (); fn call<'a, 'b>(&'a self, _input: Self::Input, next: Next<'b>) -> impl Future + 'a { async move { println!("POST_1"); next.await } } } struct PostMiddleware2; impl MiddlewareConstructor for PostMiddleware2 { type Middleware = Self; fn new() -> Self { Self } } impl Middleware for PostMiddleware2 { type Input = (); type Output = (); fn call<'a, 'b>(&'a self, _input: Self::Input, next: Next<'b>) -> impl Future + 'a { async move { println!("POST_2"); next.await } } } let mut pipeline = pavex::pipeline::Pipeline::new(); pipeline.add(PreMiddleware1); pipeline.add(PreMiddleware2); pipeline.add(GetIndex); pipeline.add(PostMiddleware1); pipeline.add(PostMiddleware2); pavex::runtime::Pavex::new(pipeline); ``` -------------------------------- ### Assemble Application Blueprint Source: https://context7.com/lukemathwalker/pavex/llms.txt Constructs the application's `Blueprint`, importing components, registering middleware and observers, and mounting routes under a specific prefix. It imports from the current crate and the `pavex` crate. ```rust use pavex::{Blueprint, blueprint::from}; // Assuming other necessary imports like TIMEOUT_WRAPPER, RESPONSE_LOGGER, ERROR_LOGGER, etc. are in scope pub fn build_blueprint() -> Blueprint { let mut bp = Blueprint::new(); // Import all constructors, error handlers and config from this crate and `pavex` bp.import(from![crate, pavex]); // Register middleware and observers // bp.wrap(TIMEOUT_WRAPPER); // bp.post_process(RESPONSE_LOGGER); // bp.error_observer(ERROR_LOGGER); // Mount all routes under /api bp.prefix("/api").routes(from![crate]); bp } ``` -------------------------------- ### Organizing Routes with Prefix, Domain, and Nesting Source: https://context7.com/lukemathwalker/pavex/llms.txt Blueprints can be composed hierarchically. `prefix` prepends a path segment, `domain` restricts routes to a specific Host header, and `nest` inserts a child blueprint. Constructors registered on a parent are inherited by nested blueprints. ```rust use pavex::{Blueprint, blueprint::from, get, Response}; #[get(path = "/users")] pub fn list_users() -> Response { Response::ok() } #[get(path = "/posts")] pub fn list_posts() -> Response { Response::ok() } #[get(path = "/metrics")] pub fn metrics() -> Response { Response::ok() } fn api_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate::api]); bp.routes(from![crate::api]); bp } fn admin_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate::admin]); // GET /metrics → only accessible via admin.example.com bp.route(METRICS); bp } pub fn root_blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.import(from![crate, pavex]); // All routes from api_blueprint get a /v1 prefix bp.prefix("/v1").nest(api_blueprint()); // Admin routes restricted to admin subdomain with /admin prefix bp.prefix("/admin").domain("admin.example.com").nest(admin_blueprint()); bp } // Resulting routes: // GET /v1/users → list_users // GET /v1/posts → list_posts // GET /admin/metrics → metrics (only for Host: admin.example.com) ``` -------------------------------- ### Define a Singleton Constructor Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/dependency_injection/constructors.md Use the `#[singleton]` attribute to define a constructor that is invoked at most once before the application starts. The same instance is injected every time the type is needed. ```rust use pavex::dependency_injection::singleton; #[singleton] struct User; impl User { fn new() -> Self { Self } } ``` -------------------------------- ### Accessing a Single Request Cookie Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/cookies/request_cookies.md Inject `RequestCookies` into your components to access client-sent cookies. Use the `get` method to retrieve a specific cookie by its name. ```rust use pavex::cookie::RequestCookies; fn my_component(cookies: &RequestCookies) -> String { let session_id = cookies.get("session_id"); format!("Session ID: {session_id:?}") } ``` -------------------------------- ### Create a Pavex Blueprint in Rust Source: https://github.com/lukemathwalker/pavex/blob/main/ARCHITECTURE.md Demonstrates how to construct a `Blueprint` by registering components like singletons, request-scoped, and transient services, and defining routes. This blueprint serves as input for code generation. ```rust use pavex::Blueprint; pub fn blueprint() -> Blueprint { let mut bp = Blueprint::new(); bp.singleton(LOAD_CONFIGURATION); bp.singleton(HTTP_CLIENT); bp.request_scoped(EXTRACT_PATH); bp.transient(LOGGER); bp.route(STREAM_FILE); bp } ``` -------------------------------- ### Annotating Free Functions with #[pavex::get] Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/attributes/functions_and_methods.md Apply `#[pavex::get]` directly above a free function to designate it as a handler for GET requests to the root path. ```rust use pavex::http::Method; use pavex::router::route; #[pavex::get] fn get_root() -> "Hello, world!".to_owned() { "Hello, world!".to_owned() } ``` -------------------------------- ### Scaffold a New Pavex Project Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/project_structure/index.md Use the `pavex new` command to create a new Pavex project with a standard directory structure. ```bash pavex new demo ``` -------------------------------- ### Import All Constructors from Crate Source: https://github.com/lukemathwalker/pavex/blob/main/docs/getting_started/quickstart/dependency_injection.md Configure the Blueprint to import all constructors defined within the current crate. ```rust use pavex::blueprint::Blueprint; let mut blueprint = Blueprint::new(); blueprint.import_components_from_cwd(); ``` -------------------------------- ### Define a Prebuilt Type Constructor Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/dependency_injection/prebuilt_types.md Use the `#[prebuilt]` attribute to mark a type as prebuilt. Pavex will expect an instance of this type to be provided during application setup. ```rust use std::sync::Arc; use pavex::prelude::*; #[derive(Clone)] pub struct DbConnectionPool {} impl DbConnectionPool { #[prebuilt] pub async fn new() -> Self { // ... connect to the database DbConnectionPool {} } } ``` -------------------------------- ### Register Routes in Bulk Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/index.md Use `Blueprint::routes` to register all routes defined in the current crate. This is a convenient way to add multiple routes at once. ```rust use pavex::blueprint::Blueprint; let mut blueprint = Blueprint::new(); blueprint.routes(pavex::routes::all()); ``` -------------------------------- ### Build and Test Pavex Source: https://github.com/lukemathwalker/pavex/blob/main/CONTRIBUTING.md Build the Pavex compiler and run the test suite. This is the primary command for verifying changes. ```bash cargo build_compiler && cargo test ``` -------------------------------- ### Fallible Request Handler Example Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/errors/index.md Demonstrates a request handler that returns a Result, indicating it can fail. This is the basis for Pavex's error handling mechanism. ```rust use pavex::response::Response; use pavex::Result; #[derive(Debug)] pub enum LoginError { InvalidCredentials, UserNotFound, } pub async fn login_user( request: http::Request, ) -> Result { // ... logic to authenticate user ... if /* credentials are invalid */ { Err(LoginError::InvalidCredentials) } else if /* user not found */ { Err(LoginError::UserNotFound) } else { Ok(Response::ok()) } } ``` -------------------------------- ### Configure Local Environment Variables in .cargo/config.toml Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/pavexc_cli/template/CONFIGURATION.md Use the [env] section in .cargo/config.toml to set environment variables for local development. Avoid storing sensitive information here. ```toml [env] # Example: PX_PROFILE=dev ``` -------------------------------- ### Dynamic Domain Guard with Multiple Parameters Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/routing/domain_guards.md Demonstrates a domain guard with multiple domain parameters separated by dots, allowing for more complex domain matching. ```rust use pavex::blueprint::{Blueprint, Route}; let mut blueprint = Blueprint::new(); blueprint.domain("{service}.{env}.pavex.dev").route(Route::get("/status").to(service_status)); ``` -------------------------------- ### Accessing Request Target in Pavex Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/request_data/request_target.md Inject `RequestHead` to access the request target via its `target` field. This example shows how to retrieve the raw target string. ```rust use pavex::request::RequestHead; let request_head: RequestHead = ...; let target = request_head.target; assert_eq!(target, "/foo/bar?baz=qux"); ``` -------------------------------- ### Registering Multiple HTTP Routes with Blueprint Source: https://context7.com/lukemathwalker/pavex/llms.txt Use `bp.routes(from![...])` to register all annotated routes discovered in the specified module sources at once. This is a convenient way to bulk-register routes. ```rust use pavex::Blueprint; use pavex::blueprint::from; pub fn routes_blueprint() -> Blueprint { let mut bp = Blueprint::new(); // Register routes one by one bp.route(GET_ARTICLE); bp.route(CREATE_ARTICLE); // Or in bulk – equivalent to registering every annotated function in the module bp.routes(from![crate::articles]); bp } ``` -------------------------------- ### Define a Wrapping Middleware with `#[wrap]` Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/wrapping.md Use the `#[wrap]` attribute to define a new wrapping middleware. This example shows how to create a middleware that enforces a request-wide timeout. ```rust use pavex::middleware::Next; use std::time::Duration; #[derive(Clone, Debug)] pub struct Timeout(Duration); #[pavex::wrap] async fn timeout(next: Next<'_>) -> Result { let response = tokio::time::timeout(Duration::from_secs(5), next).await; match response { Ok(response) => Ok(response?), Err(_) => Err(http::StatusCode::REQUEST_TIMEOUT), } } ``` -------------------------------- ### Define a Post-processing Middleware Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/middleware/post_processing.md Use the `#[post_process]` attribute to define a new post-processing middleware. This example defines a `response_logger` middleware that logs the response status code. ```rust use pavex::response::Response; #[pavex::post_process] fn response_logger(response: &Response) { log::info!("Received response with status code: {}", response.status_code()); } ``` -------------------------------- ### Pavex Component Wrapping Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/borrow_checker/multiple_consumers/a_non_cloneable_type_cannot_be_moved_twice_across_stages/expectations/stderr.txt Example of wrapping a component (`MW`) that consumes `app::A` by value. This is one of the points where the borrow checker conflict arises if `A` is not cloneable. ```rust bp.wrap(MW); ``` -------------------------------- ### Catch-all Parameter Not at the End Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/blueprint/router/invalid_paths/expectations/stderr.txt Catch-all parameters, denoted by `{*name}`, must appear at the very end of a route path. This example demonstrates an invalid placement of a catch-all parameter. ```rust #[pavex::get(path = "/{*invalid_catch_all}/hey")] pub fn invalid_catch_all() -> Response { } ``` -------------------------------- ### Configure Blueprint for Postgres Sessions Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/sessions/installation.md Set up the Pavex blueprint with necessary imports and middlewares for session management using Postgres. ```rust use pavex::blueprint::Blueprint; use pavex::cookie::{Cookie, CookieJar, ResponseCookies}; use pavex::http::StatusCode; use pavex::request::Request; use pavex::response::Response; use pavex_session::finalize_session; use pavex_session::session_store::SessionStore; use pavex_session_sqlx::postgres::PostgresSessionStore; let mut blueprint = Blueprint::new(); blueprint .route("/login", pavex::route::handler::get(login)) .route("/logout", pavex::route::handler::get(logout)); blueprint.middleware(pavex_session::middleware::SessionStorage::new(PostgresSessionStore::new())); blueprint.middleware(finalize_session); blueprint.middleware(pavex::cookie::inject_response_cookies); async fn login(session_store: SessionStore, cookies: &mut CookieJar) -> Result<(), Status> { let session_id = session_store.save_session(()).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; cookies.add(Cookie::new("session", session_id.to_string())); Ok(()) } async fn logout(session_store: SessionStore, cookies: &mut CookieJar) -> Result<(), Status> { let session_id = session_store.destroy_session().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; cookies.remove(Cookie::named("session")); Ok(()) } struct Status(StatusCode); impl From for Status { fn from(code: StatusCode) -> Self { Status(code) } } ``` -------------------------------- ### Register Prebuilt Types in Bulk Source: https://github.com/lukemathwalker/pavex/blob/main/docs/guide/dependency_injection/prebuilt_types.md Import prebuilt types from the current crate using a `use` statement to register them in bulk with Pavex's blueprint. ```rust use my_app::prebuilt_types::*; let mut blueprint = Blueprint::new(); blueprint.register(AllPrebuiltTypes); ``` -------------------------------- ### Constructor Returning Naked Generic Parameter Source: https://github.com/lukemathwalker/pavex/blob/main/compiler/ui_tests/blueprint/constructors/output_type_of_constructors_cannot_be_a_naked_generic/expectations/stderr.txt This example shows a constructor `naked() -> T` that returns a naked generic parameter `T`. This is not allowed because Pavex cannot infer the concrete type for `T`. ```rust pub fn naked() -> T { todo!() } ```