Extracting Data from Requests
warp
provides a variety of filters to extract data from incoming HTTP requests, such as query parameters, headers, and the request body.
Query Parameters
The warp::query()
filter deserializes the request's query string (e.g., ?foo=bar&baz=123
) into a specified type. The type must implement serde::Deserialize
.
Extracting to a HashMap
You can extract all query parameters into a HashMap
for dynamic access.
use std::collections::HashMap;
use warp::Filter;
// Matches requests like /example1?key=value
let route = warp::path("example1")
.and(warp::query::<HashMap<String, String>>())
.map(|p: HashMap<String, String>| {
match p.get("key") {
Some(key) => format!("key = {}", key),
None => "No 'key' param found.".to_string(),
}
});
Extracting to a Custom Struct
For more structured and type-safe data, define a struct and derive serde::Deserialize
.
use serde_derive::Deserialize;
use warp::Filter;
#[derive(Deserialize)]
struct MyObject {
key1: String,
key2: u32,
}
// Matches requests like /example2?key1=value&key2=42
let route = warp::path("example2")
.and(warp::query::<MyObject>())
.map(|p: MyObject| {
format!("key1 = {}, key2 = {}", p.key1, p.key2)
});
Headers
The warp::header
module provides filters for extracting request headers.
use std::net::SocketAddr;
use warp::Filter;
// Extract 'host' header as a SocketAddr
let host = warp::header::<SocketAddr>("host");
// Require 'accept' header to be exactly '*/*'
let accept_stars = warp::header::exact("accept", "*/*");
// Optionally extract the 'dnt' header
let dnt = warp::header::optional::<bool>("dnt");
let routes = host
.and(accept_stars)
.map(|addr: SocketAddr| format!("Accepting stars on {}", addr));
Request Body
The warp::body
module contains filters to handle the request body.
JSON Body
To deserialize a JSON request body, use warp::body::json()
. The target type must implement serde::Deserialize
.
use serde_derive::Deserialize;
use warp::Filter;
#[derive(Deserialize)]
struct Employee {
name: String,
rate: u32,
}
let promote = warp::post()
.and(warp::path("employees"))
// Protect against large bodies
.and(warp::body::content_length_limit(1024 * 16))
.and(warp::body::json())
.map(|mut employee: Employee| {
employee.rate *= 2;
warp::reply::json(&employee)
});
Form Body (URL-Encoded)
For application/x-www-form-urlencoded
bodies, use warp::body::form()
.
use std::collections::HashMap;
use warp::Filter;
let route = warp::post()
.and(warp::body::form::<HashMap<String, String>>())
.map(|map| /* ... */);
Multipart Form Data
For multipart/form-data
, used for file uploads, warp
provides warp::multipart::form()
. This filter extracts a FormData
object, which is a stream of Part
s.
use bytes::BufMut;
use futures_util::TryStreamExt;
use warp::multipart::{FormData, Part};
use warp::Filter;
let upload = warp::multipart::form()
.and_then(|form: FormData| async move {
let parts: Vec<Part> = form.try_collect().await.map_err(|e| {
eprintln!("form error: {}", e);
warp::reject::reject()
})?;
// ... process parts ...
Ok("Upload successful")
});
This is just a high-level overview. For more details on handling streams from multipart forms, see the multipart.rs
example.