A builder-like pattern is used to construct an instance of HttpResponse
. HttpResponse
provides several methods that return a HttpResponseBuilder
instance, which implements various convenience methods for building responses.
Check the documentation for type descriptions.
The methods .body
, .finish
, and .json
finalize response creation and return a constructed HttpResponse instance. If this methods is called on the same builder instance multiple times, the builder will panic.
use actix_web::{http::header::ContentType, HttpResponse};
async fn index() -> HttpResponse {
HttpResponse::Ok()
.content_type(ContentType::plaintext())
.insert_header(("X-Hdr", "sample"))
.body("data")
}
The Json
type allows to respond with well-formed JSON data: simply return a value of type Json<T>
where T
is the type of a structure to serialize into JSON. The type T
must implement the Serialize
trait from serde.
For the following example to work, you need to add serde
to your dependencies in Cargo.toml
:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
use actix_web::{get, web, Responder, Result};
use serde::Serialize;
#[derive(Serialize)]
struct MyObj {
name: String,
}
#[get("/a/{name}")]
async fn index(name: web::Path<String>) -> Result<impl Responder> {
let obj = MyObj {
name: name.to_string(),
};
Ok(web::Json(obj))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
use actix_web::{App, HttpServer};
HttpServer::new(|| App::new().service(index))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Using the Json
type this way instead of calling the .json
method on a HttpResponse
makes it immediately clear that the function returns JSON and not any other type of response.
Actix Web can automatically compress payloads with the Compress middleware. The following codecs are supported:
use actix_web::{get, middleware, App, HttpResponse, HttpServer};
#[get("/")]
async fn index_br() -> HttpResponse {
HttpResponse::Ok().body("data")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(middleware::Compress::default())
.service(index_br)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Response payload is compressed based on the encoding parameter from the middleware::BodyEncoding
trait. By default, ContentEncoding::Auto
is used. If ContentEncoding::Auto
is selected, then the compression depends on the request’s Accept-Encoding
header.
ContentEncoding::Identity
can be used to disable compression. If another content encoding is selected, the compression is enforced for that codec.
For example, to enable brotli
for a single handler use ContentEncoding::Br
:
use actix_web::{get, middleware, App, HttpResponse, HttpServer};
#[get("/")]
async fn index_br() -> HttpResponse {
HttpResponse::Ok().body("data")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(middleware::Compress::default())
.service(index_br)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
or for the entire application:
use actix_web::{http::ContentEncoding, dev::BodyEncoding, HttpResponse};
async fn index_br() -> HttpResponse {
HttpResponse::Ok().body("data")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
use actix_web::{middleware, web, App, HttpServer};
HttpServer::new(|| {
App::new()
.wrap(middleware::Compress::new(ContentEncoding::Br))
.route("/", web::get().to(index_br))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
In this case we explicitly disable content compression by setting content encoding to an Identity
value:
use actix_web::{
get, http::header::ContentEncoding, middleware, App, HttpResponse, HttpServer,
};
#[get("/")]
async fn index() -> HttpResponse {
HttpResponse::Ok()
// v- disable compression
.insert_header(ContentEncoding::Identity)
.body("data")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(middleware::Compress::default())
.service(index)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
When dealing with an already compressed body (for example when serving assets), set the content encoding to Identity
to avoid compressing the already compressed data and set the content-encoding
header manually:
use actix_web::{
get, http::header::ContentEncoding, middleware, App, HttpResponse, HttpServer,
};
static HELLO_WORLD: &[u8] = &[
0x1f, 0x8b, 0x08, 0x00, 0xa2, 0x30, 0x10, 0x5c, 0x00, 0x03, 0xcb, 0x48, 0xcd, 0xc9, 0xc9,
0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1, 0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
0x00, 0x00,
];
#[get("/")]
async fn index() -> HttpResponse {
HttpResponse::Ok()
.insert_header(ContentEncoding::Gzip)
.body(HELLO_WORLD)
}
Also it is possible to set default content encoding on application level, by default ContentEncoding::Auto
is used, which implies automatic content compression negotiation.
use actix_web::{get, middleware, App, HttpResponse, HttpServer};
#[get("/")]
async fn index() -> HttpResponse {
HttpResponse::Ok().body("data")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(middleware::Compress::default())
.service(index)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}