Struct App

Source
pub struct App { /* private fields */ }
Expand description

The main application builder for Torch web framework.

App is the central component that ties together routing, middleware, state management, and server configuration. It follows a builder pattern for easy configuration and provides a fluent API for defining routes and middleware.

§Examples

§Basic Usage

use torch_web::{App, Request, Response};

let app = App::new()
    .get("/", |_req: Request| async {
        Response::ok().body("Hello, World!")
    })
    .post("/users", |_req: Request| async {
        Response::created().body("User created")
    });

§With Middleware

use torch_web::{App, Request, Response};

let app = App::new()
    .middleware(torch_web::middleware::logger())
    .middleware(torch_web::middleware::cors())
    .get("/api/users", |_req: Request| async {
        Response::ok().json(&serde_json::json!({"users": []}))
    });

§With Application State

use torch_web::{App, Request, Response, extractors::State};
use std::sync::Arc;

#[derive(Clone)]
struct AppState {
    counter: Arc<std::sync::atomic::AtomicU64>,
}

let state = AppState {
    counter: Arc::new(std::sync::atomic::AtomicU64::new(0)),
};

let app = App::new()
    .with_state(state)
    .get("/count", |State(state): State<AppState>| async move {
        let count = state.counter.load(std::sync::atomic::Ordering::SeqCst);
        Response::ok().body(format!("Count: {}", count))
    });

§Production-Ready Configuration

use torch_web::App;

let app = App::with_defaults() // Includes security, monitoring, CORS
    .get("/health", |_req| async {
        Response::ok().json(&serde_json::json!({"status": "healthy"}))
    });

Implementations§

Source§

impl App

Convenience methods for App to add documented endpoints

Source

pub fn documented_get<H, T>( self, path: &str, handler: H, doc: EndpointDoc, ) -> Self
where H: Handler<T>,

Add a documented GET endpoint

Source

pub fn documented_post<H, T>( self, path: &str, handler: H, doc: EndpointDoc, ) -> Self
where H: Handler<T>,

Add a documented POST endpoint

Source§

impl App

Source

pub fn new() -> Self

Creates a new application instance with default configuration.

This initializes an empty application with:

  • A new router with no routes
  • An empty middleware stack
  • Default error pages
  • Empty state map
§Examples
use torch_web::App;

let app = App::new();
Source

pub fn with_state<T>(self, state: T) -> Self
where T: Clone + Send + Sync + 'static,

Adds application state that can be accessed in handlers via the State extractor.

Application state allows you to share data across all handlers, such as database connections, configuration, or any other shared resources. The state must implement Clone + Send + Sync + 'static.

§Type Parameters
  • T - The type of state to add. Must be Clone + Send + Sync + 'static.
§Examples
use torch_web::{App, Request, Response, extractors::State};
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};

#[derive(Clone)]
struct AppState {
    counter: Arc<AtomicU64>,
}

let state = AppState {
    counter: Arc::new(AtomicU64::new(0)),
};

let app = App::new()
    .with_state(state)
    .get("/count", |State(state): State<AppState>| async move {
        let count = state.counter.fetch_add(1, Ordering::SeqCst);
        Response::ok().body(format!("Count: {}", count))
    });
Source

pub fn middleware<M>(self, middleware: M) -> Self
where M: Middleware,

Adds middleware to the application’s middleware stack.

Middleware is executed in the order it’s added, wrapping the final route handler. Each middleware can modify the request before it reaches the handler and/or modify the response before it’s sent to the client.

§Type Parameters
  • M - The middleware type. Must implement the Middleware trait.
§Examples
use torch_web::{App, middleware};

let app = App::new()
    .middleware(middleware::logger())
    .middleware(middleware::cors())
    .get("/", |_req| async { Response::ok().body("Hello!") });
§Custom Middleware
use torch_web::{App, Request, Response, middleware::Middleware};
use std::pin::Pin;
use std::future::Future;

struct CustomMiddleware;

impl Middleware for CustomMiddleware {
    fn call(
        &self,
        req: Request,
        next: Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'static>> + Send + Sync>,
    ) -> Pin<Box<dyn Future<Output = Response> + Send + 'static>> {
        Box::pin(async move {
            // Modify request here
            let mut response = next(req).await;
            // Modify response here
            response = response.header("X-Custom", "middleware");
            response
        })
    }
}

let app = App::new().middleware(CustomMiddleware);
Source

pub fn route<H, T>(self, method: Method, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a route for any HTTP method with the specified path and handler.

This is the most flexible route registration method that allows you to specify any HTTP method. For common methods, consider using the convenience methods like get, post, put, etc.

§Parameters
  • method - The HTTP method to match (GET, POST, PUT, DELETE, etc.)
  • path - The URL path pattern to match. Supports parameters like /users/:id
  • handler - The handler function to execute when the route matches
§Path Parameters

Paths can include parameters using the :name syntax:

  • /users/:id matches /users/123 and captures id = "123"
  • /posts/:id/comments/:comment_id captures multiple parameters
  • Use the Path extractor to access parameters in handlers
§Examples
use torch_web::{App, Request, Response, Method};

let app = App::new()
    .route(Method::GET, "/", |_req: Request| async {
        Response::ok().body("Hello, World!")
    })
    .route(Method::POST, "/users", |_req: Request| async {
        Response::created().body("User created")
    });
Source

pub fn get<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a GET route handler.

GET requests are typically used for retrieving data and should be idempotent (safe to repeat). Perfect for serving web pages, API endpoints that fetch data, and static resources.

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response, extractors::Path};

let app = App::new()
    .get("/", |_req: Request| async {
        Response::ok().body("Welcome to Torch!")
    })
    .get("/users/:id", |Path(id): Path<u32>| async move {
        Response::ok().body(format!("User ID: {}", id))
    })
    .get("/api/users", |_req: Request| async {
        Response::ok().json(&serde_json::json!({"users": []}))
    });
Source

pub fn post<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a POST route handler.

POST requests are typically used for creating new resources or submitting data. They are not idempotent and can have side effects.

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response, extractors::Json};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct CreateUser {
    name: String,
    email: String,
}

let app = App::new()
    .post("/users", |Json(user): Json<CreateUser>| async move {
        // Create user logic here
        Response::created().json(&user)
    })
    .post("/login", |_req: Request| async {
        Response::ok().body("Login successful")
    });
Source

pub fn put<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a PUT route handler.

PUT requests are typically used for updating entire resources or creating resources with a specific ID. They should be idempotent.

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response, extractors::{Path, Json}};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct UpdateUser {
    name: String,
    email: String,
}

let app = App::new()
    .put("/users/:id", |Path(id): Path<u32>, Json(user): Json<UpdateUser>| async move {
        // Update user logic here
        Response::ok().json(&user)
    });
Source

pub fn delete<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a DELETE route handler.

DELETE requests are used for removing resources. They should be idempotent (deleting a non-existent resource should not cause an error).

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response, extractors::Path};

let app = App::new()
    .delete("/users/:id", |Path(id): Path<u32>| async move {
        // Delete user logic here
        Response::no_content()
    })
    .delete("/posts/:id", |Path(id): Path<u32>| async move {
        Response::ok().body(format!("Deleted post {}", id))
    });
Source

pub fn patch<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a PATCH route handler.

PATCH requests are used for partial updates to resources. Unlike PUT, PATCH only updates the specified fields rather than replacing the entire resource.

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response, extractors::{Path, Json}};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct PatchUser {
    name: Option<String>,
    email: Option<String>,
}

let app = App::new()
    .patch("/users/:id", |Path(id): Path<u32>, Json(patch): Json<PatchUser>| async move {
        // Partial update logic here
        Response::ok().json(&patch)
    });
Source

pub fn options<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers an OPTIONS route handler.

OPTIONS requests are typically used for CORS preflight requests to check what methods and headers are allowed for cross-origin requests.

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response};

let app = App::new()
    .options("/api/*", |_req: Request| async {
        Response::ok()
            .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
            .header("Access-Control-Allow-Headers", "Content-Type, Authorization")
            .body("")
    });
Source

pub fn head<H, T>(self, path: &str, handler: H) -> Self
where H: Handler<T>,

Registers a HEAD route handler.

HEAD requests are identical to GET requests except that the server must not return a message body. They’re useful for checking if a resource exists or getting metadata without downloading the full content.

§Parameters
  • path - The URL path pattern to match
  • handler - The handler function to execute
§Examples
use torch_web::{App, Request, Response};

let app = App::new()
    .head("/users/:id", |_req: Request| async {
        // Check if user exists and return appropriate headers
        Response::ok()
            .header("Content-Type", "application/json")
            .header("Content-Length", "42")
    });
Source

pub fn not_found<H, T>(self, handler: H) -> Self
where H: Handler<T>,

Sets a custom handler for requests that don’t match any registered route.

By default, unmatched requests return a 404 Not Found response. This method allows you to customize that behavior with your own handler.

§Parameters
  • handler - The handler function to execute for unmatched routes
§Examples
use torch_web::{App, Request, Response};

let app = App::new()
    .get("/", |_req: Request| async {
        Response::ok().body("Home")
    })
    .not_found(|req: Request| async move {
        Response::not_found()
            .body(format!("Sorry, {} was not found", req.path()))
    });
Source

pub fn mount(self, prefix: &str, other: Router) -> Self

Mounts another router at a specific path prefix.

This allows you to modularize your application by creating separate routers for different parts of your API and then mounting them under different prefixes. All routes from the mounted router will be prefixed with the specified path.

§Parameters
  • prefix - The path prefix to mount the router under (e.g., “/api/v1”)
  • other - The router to mount
§Examples
use torch_web::{App, Router, Request, Response};

// Create a router for user-related endpoints
let mut user_router = Router::new();
user_router.get("/", |_req: Request| async {
    Response::ok().body("List users")
});
user_router.get("/:id", |_req: Request| async {
    Response::ok().body("Get user")
});

// Mount it under /api/users
let app = App::new()
    .get("/", |_req: Request| async {
        Response::ok().body("Home")
    })
    .mount("/api/users", user_router);

// Now you have:
// GET / -> "Home"
// GET /api/users/ -> "List users"
// GET /api/users/:id -> "Get user"
Source

pub fn error_pages(self, error_pages: ErrorPages) -> Self

Configures custom error pages for the application.

This replaces the default error page configuration with a custom one. Use this when you want full control over error page rendering.

§Parameters
  • error_pages - The custom error pages configuration
§Examples
use torch_web::{App, ErrorPages};

let custom_errors = ErrorPages::new()
    .custom_404("<h1>Page Not Found</h1>".to_string())
    .custom_500("<h1>Server Error</h1>".to_string());

let app = App::new()
    .error_pages(custom_errors);
Source

pub fn custom_404(self, html: String) -> Self

Sets a custom HTML template for 404 Not Found errors.

This is a convenience method for setting just the 404 error page without having to create a full ErrorPages configuration.

§Parameters
  • html - The HTML content to display for 404 errors
§Examples
use torch_web::App;

let app = App::new()
    .custom_404(r#"
        <html>
            <body>
                <h1>🔥 Torch doesn't know this route!</h1>
                <p>The page you're looking for doesn't exist.</p>
            </body>
        </html>
    "#.to_string());
Source

pub fn custom_500(self, html: String) -> Self

Sets a custom HTML template for 500 Internal Server Error responses.

This is a convenience method for setting just the 500 error page without having to create a full ErrorPages configuration.

§Parameters
  • html - The HTML content to display for 500 errors
§Examples
use torch_web::App;

let app = App::new()
    .custom_500(r#"
        <html>
            <body>
                <h1>🔥 Something went wrong!</h1>
                <p>We're working to fix this issue.</p>
            </body>
        </html>
    "#.to_string());
Source

pub fn plain_error_pages(self) -> Self

Disables the default error page styling and uses plain HTML.

By default, Torch adds CSS styling to error pages. This method disables that styling if you prefer plain HTML or want to add your own styling.

§Examples
use torch_web::App;

let app = App::new()
    .plain_error_pages()
    .custom_404("<h1>Not Found</h1>".to_string());
Source

pub fn websocket<F, Fut>(self, _path: &str, _handler: F) -> Self
where F: Fn() -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<(), Box<dyn Error + Send + Sync>>> + Send + 'static,

No-op WebSocket method when the websocket feature is disabled.

This method exists to provide a consistent API regardless of whether the websocket feature is enabled. When the feature is disabled, this method does nothing and returns the app unchanged.

Source

pub async fn listen( self, addr: &str, ) -> Result<(), Box<dyn Error + Send + Sync>>

Starts the HTTP server and begins listening for incoming requests.

This method consumes the App and starts the server on the specified address. The server will run until the process is terminated or an error occurs.

§Parameters
  • addr - The address to bind to (e.g., “127.0.0.1:3000” or “0.0.0.0:8080”)
§Returns

Returns Ok(()) if the server shuts down gracefully, or an error if the server fails to start or encounters a fatal error.

§Examples
§Basic Server
use torch_web::{App, Request, Response};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let app = App::new()
        .get("/", |_req: Request| async {
            Response::ok().body("Hello, World!")
        });

    app.listen("127.0.0.1:3000").await
}
§Production Server
use torch_web::App;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let app = App::with_defaults()
        .get("/health", |_req| async {
            Response::ok().json(&serde_json::json!({"status": "healthy"}))
        });

    // Bind to all interfaces in production
    app.listen("0.0.0.0:8080").await
}
Source§

impl App

Pre-configured application constructors for common scenarios.

These methods provide sensible defaults for different types of applications, saving you from having to manually configure common middleware combinations.

Source

pub fn with_logging() -> Self

Creates a new app with request logging middleware enabled.

This is useful for development and debugging, as it logs all incoming requests with their method, path, and response status.

§Examples
use torch_web::{App, Request, Response};

let app = App::with_logging()
    .get("/", |_req: Request| async {
        Response::ok().body("Hello, World!")
    });
Source

pub fn with_cors() -> Self

Creates a new app with CORS (Cross-Origin Resource Sharing) middleware enabled.

This allows your API to be accessed from web browsers running on different domains. Useful for frontend applications that need to call your API.

§Examples
use torch_web::{App, Request, Response};

let app = App::with_cors()
    .get("/api/data", |_req: Request| async {
        Response::ok().json(&serde_json::json!({"data": "value"}))
    });
Source

pub fn with_defaults() -> Self

Creates a production-ready app with comprehensive middleware stack.

This includes:

  • Request logging and monitoring
  • Performance metrics collection
  • Security headers (HSTS, CSP, etc.)
  • Request ID generation
  • Input validation
  • CORS support
  • Request timeout (30 seconds)
  • Request size limit (16MB)
  • Health check endpoint
§Examples
use torch_web::{App, Request, Response};

let app = App::with_defaults()
    .get("/", |_req: Request| async {
        Response::ok().body("Production app")
    })
    .get("/api/users", |_req: Request| async {
        Response::ok().json(&serde_json::json!({"users": []}))
    });
Source

pub fn with_security() -> Self

Creates an app with essential security middleware enabled.

This includes:

  • Security headers (HSTS, CSP, X-Frame-Options, etc.)
  • Request ID generation for tracking
  • Input validation to prevent common attacks
§Examples
use torch_web::{App, Request, Response};

let app = App::with_security()
    .get("/secure-endpoint", |_req: Request| async {
        Response::ok().body("This endpoint has security headers")
    });
Source

pub fn with_monitoring() -> Self

Creates an app with monitoring and metrics collection enabled.

This includes:

  • Request logging
  • Performance metrics collection
  • Performance monitoring
  • Health check endpoint at /health
§Examples
use torch_web::{App, Request, Response};

let app = App::with_monitoring()
    .get("/api/status", |_req: Request| async {
        Response::ok().json(&serde_json::json!({"status": "ok"}))
    });

Trait Implementations§

Source§

impl Default for App

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for App

§

impl !RefUnwindSafe for App

§

impl Send for App

§

impl Sync for App

§

impl Unpin for App

§

impl !UnwindSafe for App

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more