Typed Headers
1. Welcome and Icebreaker:
What’s the most unusual HTTP header you’ve seen or used? Share your answer in the chat!
2. Outline the Session:
Agenda:
- Concept Explanation: Using
TypedHeaderto extract HTTP headers in Axum. - Live Coding: Extract and use headers like
AuthorizationandUser-Agent. - Tasks: Practice by working with custom and standard headers.
Learning Outcomes:
- Use
axum_extra::TypedHeaderto extract and use HTTP headers. - Understand how to work with standard and custom headers in handlers.
- Learn to handle missing or malformed headers gracefully.
- Add custom headers to responses.
Expectations: Try extracting different headers and see how they are used! Ask questions if anything is unclear.
3. Concept Explanation:
HTTP headers carry important metadata with requests, such as authentication tokens, client information, and custom data. The optional axum-extra crate provides TypedHeader for standard headers such as User-Agent and Authorization; it is not in axum::extract. For arbitrary headers, use HeaderMap or implement headers::Header.
Axum leverages the headers crate, which provides types for many common HTTP headers. For custom headers, you can define your own types by implementing the necessary traits.
Why use Typed Headers?
- Type Safety: Prevents mistakes from manual parsing.
- Clarity: Handlers clearly state which headers they expect.
- Extensibility: Easily add support for new or custom headers.
How does it work?
- Use
TypedHeader<T>in your handler’s parameters, whereTis a type from theheaderscrate or your own custom type. - If the header is present and valid, Axum injects it into your handler. If not, you can handle the error or provide a default.
4. Live Coding Demonstration:
Add axum-extra = { version = "0.12", features = ["typed-header"] } and headers = "0.4" alongside Axum 0.8 and Tokio 1. This example uses the standard Authorization: Bearer ... scheme; never echo real credentials in responses or logs.
use axum::{Router, routing::get, response::{IntoResponse, Response}, http::StatusCode};
use axum_extra::TypedHeader;
use headers::{UserAgent, Authorization, authorization::Bearer};
// Handler to extract User-Agent header
async fn user_agent(TypedHeader(user_agent): TypedHeader<UserAgent>) -> String {
format!("User-Agent: {}", user_agent)
}
// Handler to extract Authorization header and handle missing/malformed cases
async fn auth_header(header: Result<TypedHeader<Authorization<Bearer>>, axum_extra::typed_header::TypedHeaderRejection>) -> impl IntoResponse {
match header {
Ok(TypedHeader(_auth)) => (StatusCode::OK, "Bearer header received"),
Err(_) => (StatusCode::UNAUTHORIZED, "Missing or malformed Bearer header"),
}
}
// Handler to add a custom header to the response
async fn custom_header() -> Response {
([("x-custom-header", "my-value")], "Custom header set!").into_response()
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/ua", get(user_agent))
.route("/auth", get(auth_header))
.route("/custom", get(custom_header));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Step-by-step explanation:
user_agent: Extracts theUser-Agentheader using theUserAgenttype from theheaderscrate.auth_header: UsesResult<TypedHeader<Authorization<Bearer>>, _>to distinguish success from rejection and return 401; validating the token itself requires additional logic.Option<TypedHeader<T>>only handles an absent header; a malformed present header is still rejected.custom_header: Demonstrates how to add a custom header to your response.
Best Practices:
- Use typed headers for safety and clarity.
- Validate header values as needed.
- Use
Result<TypedHeader<T>, _>if you need to customize the rejection for absent or malformed headers. - Add
axum-extrawithtyped-headerand theheaderscrate to your dependencies.
Common Pitfalls:
- Not enabling the
typed-headerfeature onaxum-extra. - Forgetting to handle missing or malformed headers (the default is a client-error rejection, not a panic).
- Not documenting which headers your handler expects.
5. Tasks
- Extract an
Authorizationheader and return a safe acknowledgement. Try both with and without the header. - Add a custom header (e.g.,
X-Custom-Header) to a response and verify it using a tool likecurlor Postman. - Modify the handler to handle missing headers gracefully (e.g., return a helpful message or a 401 status).
- (Bonus) Define and extract a custom header type using the
headerscrate’s traits.