HTTP Requests & Responses
Understand the lifecycle of requests and how to craft responses.
Learning Objectives
- Read request data
- Build HTTP responses
##The request and the response
Every interaction with your server is a pair: a request from the client and a response from you. Understanding both parts makes the rest of Actix Web much easier.
#Anatomy of a request
A request has four parts:
- Method: what the client wants to do (
GET,POST,PUT,DELETE). - Path and query: which resource (
/users/42?active=true). - Headers: metadata such as
Content-Type,AuthorizationandUser-Agent. - Body: optional data, usually JSON for
POSTandPUT.
You can inspect the raw request by taking HttpRequest as a parameter:
use actix_web::{get, HttpRequest, HttpResponse};
#[get("/inspect")]
async fn inspect(req: HttpRequest) -> HttpResponse {
let ua = req
.headers()
.get("user-agent")
.and_then(|v| v.to_str().ok())
.unwrap_or("unknown");
HttpResponse::Ok().body(format!("{} {} from {}", req.method(), req.path(), ua))
}#Anatomy of a response
A response has a status code, headers and an optional body. HttpResponse is the builder:
use actix_web::{http::header, HttpResponse};
fn example() -> HttpResponse {
HttpResponse::Ok()
.insert_header((header::CACHE_CONTROL, "no-store"))
.content_type("text/plain; charset=utf-8")
.body("hello")
}#Status codes you will use constantly
200 OK: success with a body.201 Created: a new resource was made.204 No Content: success with nothing to return.400 Bad Request: the client sent something invalid.401/403: not logged in / not allowed.404 Not Found: the resource does not exist.500 Internal Server Error: your server failed.
Actix has a shortcut for each: HttpResponse::Created(), HttpResponse::NotFound(), HttpResponse::BadRequest() and so on.
#Anything can be a response
Many types implement Responder, so for simple cases you can skip HttpResponse entirely: a &str or String becomes a 200 text response, web::Json<T> becomes JSON, and a tuple like (body, StatusCode::CREATED) sets the status.
Choose HttpResponse when you need to control headers or the status, and a plain value when you do not.
Interactive Code Inspector
Select any highlighted line of code below to deeply inspect its mechanics, understand why it exists, and what happens if you change it.
"What If?" Experiment
Learning by doing. Modify the code to see what happens.
Add a custom header to a response.
Add .insert_header(("X-App", "ActixWeb")) before .body.
The response now includes the header X-App: ActixWeb.
Explanation: HttpResponse is a builder, so each call adds to the response before you finish it with body, json or finish.
Common Mistakes
Anticipate and avoid these frequent pitfalls when working with this concept.
Returning 200 for errors
It feels simpler to always return Ok, but clients rely on the status code.
Explanation: Browsers, caches and API clients use the status code to decide what happened. Use the code that matches the outcome.
Forgetting the Content-Type for JSON
Writing JSON text into body() does not set the header.
Explanation: .json() serializes the value and sets Content-Type to application/json, so clients parse it correctly.
Practical Exercise
Return the right status codes
TaskWrite a handler for DELETE /items/{id} that returns 204 when id is 1 and 404 otherwise.
Requirements
- Read id from the path as a u32
- Return HttpResponse::NoContent() for id 1
- Return HttpResponse::NotFound() for anything else
Need a hint?
Try solving the exercise in your local environment first. Once you have a solution, or if you get completely stuck, reveal the answer.
Real-World Application
Public APIs are judged by their status codes and headers: caching headers control CDN behaviour, 201 with a Location header signals creation, and consistent 4xx responses make clients easy to write.
Key Takeaways
- A request is method + path + headers + optional body; a response is status + headers + optional body.
- HttpRequest gives you raw access; extractors are usually cleaner.
- HttpResponse::Ok(), Created(), NotFound() and friends set the status code.
- Strings, web::Json and tuples already implement Responder.
Finished reading?
Mark this lesson as done to track your progress and earn XP.