响应
response.md
commit - 47473dc4bbd1a54ef135bea5cac1d04590dba986 - 2020.09.19
使用类似于 builder 的模式构造 HttpResponse
实例。HttpResponse
提供了返回 HttpResponseBuilder
实例的几种方法,HttpResponseBuilder
实例实现了多种便捷方法用于生成响应。
可查看文档中的类型描述。
方法 .body
、.finish
,以及 .json
完成响应创建,并返回一个已构造的 HttpResponse 实例。如果在同一个 builder 实例上多次调用此方法,builder 将会抛出异常。
use actix_web::HttpResponse;
async fn index() -> HttpResponse {
HttpResponse::Ok()
.content_type("plain/text")
.header("X-Hdr", "sample")
.body("data")
}
内容编码
actix-web 可以使用 Compress 中间价自动压缩 有效负载。支持以下编解码器:
- Brotli
- Gzip
- Deflate
- Identity
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
}
响应负载基于中间价 middleware::BodyEncoding
trait 中的 encoding 参数进行压缩。默认情况下,使用参数 ContentEncoding::Auto
。如果选择使用参数 ContentEncoding::Auto
,则压缩取决于请求的 Accept-Encoding
消息标头。
ContentEncoding::Identity
可用于禁用压缩。如果选择了其它内容编码方式,则对该编解码器强制压缩。
例如,要为单个 handler 启用 brotli
,请使用 ContentEncoding::Br
:
use actix_web::{
dev::BodyEncoding, get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer,
};
#[get("/")]
async fn index_br() -> HttpResponse {
HttpResponse::Ok()
.encoding(ContentEncoding::Br)
.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
}
或者对于整个应用程序:
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
}
在这种情况下,我们通过将内容编码设置为 Identity
值来显式禁用内容压缩:
use actix_web::{
dev::BodyEncoding, get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer,
};
#[get("/")]
async fn index() -> HttpResponse {
HttpResponse::Ok()
// v- disable compression
.encoding(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
}
在处理已压缩的正文主体(例如处理服务器静态资源文件)时,将内容编码设置为 Identity
,以避免压缩已压缩的数据,同时需要手动设置 content-encoding
消息表头:
use actix_web::{
dev::BodyEncoding, get, http::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()
.encoding(ContentEncoding::Identity)
.header("content-encoding", "gzip")
.body(HELLO_WORLD)
}
也可以在应用程序级别设置默认内容编码,默认情况下使用 ContentEncoding::Auto
,这意味着可修改的自动内容压缩。
use actix_web::{get, http::ContentEncoding, 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::new(ContentEncoding::Br))
.service(index)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
JSON 响应
Json
类型允许使用符合语法规则的 Json 数据进行响应:只需返回 Json<T>
类型的值,其中 T
是要序列化为 JSON 的结构类型。类型 T
必须实现 serde crate 中的 Serialize
trait。
use actix_web::{get, web, HttpResponse, Result};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct MyObj {
name: String,
}
#[get("/a/{name}")]
async fn index(obj: web::Path<MyObj>) -> Result<HttpResponse> {
Ok(HttpResponse::Ok().json(MyObj {
name: obj.name.to_string(),
}))
}
#[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
}