How to handle form data

Web
Use the `axum::extract::Form` extractor with the `form_urlencoded` crate to automatically parse `application/x-www-form-urlencoded` data into a strongly typed struct.

Use the axum::extract::Form extractor with the form_urlencoded crate to automatically parse application/x-www-form-urlencoded data into a strongly typed struct. For multipart form data (file uploads), use axum::extract::Multipart to stream parts individually, as the full payload cannot be loaded into memory at once.

For standard text forms, define a struct matching your input fields and derive Deserialize. Axum handles the parsing and validation automatically, returning a 400 error if the data is malformed.

use axum::{
    extract::Form,
    response::Html,
    routing::post,
    Router,
};
use serde::Deserialize;

#[derive(Deserialize)]
struct LoginInput {
    username: String,
    password: String,
}

async fn handle_login(Form(input): Form<LoginInput>) -> Html<String> {
    // Access fields directly: input.username, input.password
    Html(format!("Hello, {}!", input.username))
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/login", post(handle_login));
    // Run server...
}

For file uploads, you must handle the Multipart stream manually. Iterate over the stream, check the content type, and save the file part to disk using tokio::fs.

use axum::{
    extract::Multipart,
    response::Html,
    routing::post,
    Router,
};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;

async fn handle_upload(mut multipart: Multipart) -> Html<String> {
    let mut filename = String::new();
    
    while let Some(field) = multipart.next_field().await.unwrap() {
        let data = field.bytes().await.unwrap();
        let name = field.content_disposition().unwrap().get_filename().unwrap_or("file.txt");
        
        filename = name.to_string();
        
        let mut file = File::create(name).await.unwrap();
        file.write_all(&data).await.unwrap();
    }
    
    Html(format!("Uploaded: {}", filename))
}

Remember to add form_urlencoded = "1.0" to your Cargo.toml if you are using Form, and ensure your HTML form uses enctype="multipart/form-data" for file uploads. Always validate input lengths and types in production to prevent buffer overflows or logic errors.