Volga
Home
Agent Skill
API Docs
GitHub
  • English
  • Русский
Home
Agent Skill
API Docs
GitHub
  • English
  • Русский
  • Home
  • Getting Started

    • Quick Start
    • Handlers
    • Route Parameters
    • Query Parameters
    • Route Groups
  • Requests & Responses

    • Headers
    • Handling JSON
    • Handling Form Data
    • Working with Files
    • Multipart Responses
    • Raw Request Body
    • Cookies
    • Validating Requests
  • Middleware & Infrastructure

    • Basic Middleware
    • Custom Middleware
    • Parameterized Middleware
    • Response Compression
    • Request Decompression
    • CORS (Cross-Origin Resource Sharing)
    • Static Files
    • Rate Limiting
    • Configuration Files
    • OpenAPI
  • Security & Access

    • Authentication and Authorization
    • OAuth 2.1 & OpenID Connect
    • OAuth 2.1 Client
    • Machine-to-Machine Grants
    • DPoP — Sender-Constrained Tokens
  • Reliability & Observability

    • Global Error Handling
    • Tracing & Logging
    • Request cancellation
    • Graceful Shutdown
  • Protocols & Realtime

    • HTTP Versions and Methods
    • HTTPS
    • WebSockets
    • Server-Sent Events (SSE)
  • Advanced Patterns

    • Dependency Injection
    • Custom Handling of HEAD, OPTIONS, and TRACE Methods
  • Agent Skill

Custom Handling of HEAD, OPTIONS, and TRACE Methods

Implementing HTTP methods such as HEAD, OPTIONS, and TRACE with the Volga can be streamlined using well-defined steps. This guide presents effective ways to handle these methods in your Volga application.

HEAD Method

By default, a handler mapped to the GET method also answers HEAD: routing hands a HEAD request that has no route of its own to the GET route, and the body is dropped on the way out.

A HEAD request therefore travels through everything its GET route travels through — the route's middleware, its group's, and its CORS policy. A HEAD-based health check against a route behind authorize is answered 401 / 403 like the GET beside it; a path where HEAD should fail needs a map_head of its own that says so.

To customize the behavior for the HEAD method, explicitly define it using the map_head method. map_head still takes precedence and runs its own middleware and none of the GET route's:

use volga::{App, ok};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let mut app = App::new();

    // HEAD /resource
    app.map_head("/resource", || async {
        ok!([
            ("x-custom-header", "some-value-get")
        ])
    });

    // GET /resource
    app.map_get("/resource", || async {
        ok!("Hello World!"; [
            ("x-custom-header", "some-value-get")
        ])
    });

    app.run().await
}

Here, the HEAD method returns headers without a body, often mirroring the headers that a GET request would have returned.

Tips

A GET and a HEAD mapped for the same path describe one resource, so they must name their route parameters identically — map_get("/file/{id}", ..) beside map_head("/file/{name}", ..) panics at registration. See Route Parameters.

OPTIONS Method

For specifically handling OPTIONS requests, use the map_options method to map this HTTP method:

use volga::{App, ok};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let mut app = App::new();

    // OPTIONS /resource
    app.map_options("/resource", || async {
        ok!([
            ("Allow", "GET, OPTIONS")
        ])
    });

    // GET /resource
    app.map_get("/resource", || async {
        ok!("Hello World!")
    });

    app.run().await
}

The example above includes the Allow header to indicate supported HTTP methods for the resource. The response body is optional, based on the specific needs of your API.

TRACE Method

The TRACE method is useful for debugging, as it enables tracing the request path to the server and returns the request message for diagnostic purposes:

use volga::{App, HttpRequest, stream};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let mut app = App::new();

    // TRACE /
    app.map_trace("/", |req: HttpRequest| async move {
        let body = req.into_body().into_data_stream();
        stream!(body; [
            ("content-type", "message/http")
        ])
    });

    app.run().await
}

This handler captures the incoming request and sends it back in the response with the appropriate content type.

You can check th examples here:

  • HEAD
  • OPTIONS
  • TRACE
Last Updated: 9/14/26, 6:45 AM
Prev
Dependency Injection