Volga
Home
API Docs
GitHub
  • English
  • Русский
Home
API Docs
GitHub
  • English
  • Русский
  • Home
  • Basics

    • Quick Start
    • Route Parameters
    • Query Parameters
    • Route Groups
    • Headers
  • Data Formats

    • Handling JSON
    • Handling Form Data
    • Working with Files
    • Server-Sent Events (SSE)
  • Protocols

    • HTTP/1 and HTTP/2
    • HTTPS
    • WebSockets & WebTransport
  • Advanced

    • Custom Middleware
    • Response Compression
    • Request Decompression
    • Global Error Handling
    • Dependency Injection
    • Tracing & Logging
    • Static Files
    • CORS (Cross-Origin Resource Sharing)
    • Cookies
    • Request cancellation
    • Custom Handling of HEAD, OPTIONS, and TRACE Methods

Handling Form Data

Volga can help to easily handle a form data in your web applications, both for ingesting incoming data in requests and sending form data responses.

Receiving Form Data

To accept a form data body in a request and deserialize it into a strongly-typed entity, use the Form<T> struct. Where T should be a deserializable struct or HashMap. For the struct ensure it derives from Deserialize from serde:

use volga::{App, Form, ok};
use serde::Deserialize;
 
#[derive(Deserialize)]
struct User {
    name: String,
    age: i32
}

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

    // POST /hello
    // name=John&age=35
    app.map_post("/hello", |user: Form<User>| async move {
        ok!("Hello {}!", user.name)
    });

    app.run().await
}

To test this endpoint, you can use the curl command like this:

curl -X POST "http://127.0.0.1:7878/hello" -H "Content-Type: application/x-www-form-urlencoded" --data-urlencode name=John&age=35
Hello John!

Tips

Similarly to Json<T> you can wrap your struct fields into Option<T> to make them optional.

Sending Form Data

To send a form data response you can leverage the form! macro:

use volga::{App, Form, form};
use serde::Serialize;
 
#[derive(Serialize)]
struct User {
    name: String,
    age: i32
}

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

    app.map_get("/user/{name}", |name: String| async move {
        let user: User = User {
            name,
            age: 35
        };
        form!(user)
    });

    app.run().await
}

Alternatively, by specifying a Form<T> as a return type you can return a struct of your type directly, thanks to IntoResponse trait:

use volga::{App, Form};
use serde::Serialize;
 
#[derive(Serialize)]
struct User {
    name: String,
    age: i32
}

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

    app.map_get("/user/{name}", get_user);

    app.run().await
}

async fn get_user(name: String) -> Form<User> {
    let user: User = User {
        name,
        age: 35
    };
    user.into() //or Form(user)
}

Here is the full example

Last Updated:
Prev
Handling JSON
Next
Working with Files