请求
request.md
commit - 4d8d53cea59bca095ca5c02ef81f0b1791736855 - 2020.09.12
内容密码
actix-web 可对有效负载自动解压缩。支持如下编解码器:
- Brotli
- Chunked
- Compress
- Gzip
- Deflate
- Identity
- Trailers
- EncodingExt
如果请求消息标头包含 Content-Encoding
消息标头,则根据消息标头值解压缩请求负载。不支持多个编解码器,即:Content-Encoding: br, gzip
。
JSON 请求
对于 json 主体正文的反序列化,有多个选项。
第一个选项是使用 Json 提取器。首先,定义一个 handler 函数,接受 Json<T>
作为参数;然后,使用 .to()
方法注册该 handler。也可以通过使用 serde_json::Value
,作为类型 T
来接受任意有效的 json 对象。
use actix_web::{web, App, HttpServer, Result};
use serde::Deserialize;
#[derive(Deserialize)]
struct Info {
username: String,
}
/// extract `Info` using serde
async fn index(info: web::Json<Info>) -> Result<String> {
Ok(format!("Welcome {}!", info.username))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().route("/", web::post().to(index)))
.bind("127.0.0.1:8080")?
.run()
.await
}
你还可以手动将有效负载加载到内存中,然后对其反序列化。
在下面的示例中,我们将反序列化 MyObj 结构体。我们需要先加载请求主体,然后将 json 反序列化到一个对象中。
use actix_web::{error, post, web, App, Error, HttpResponse};
use futures::StreamExt;
use serde::{Deserialize, Serialize};
use serde_json;
#[derive(Serialize, Deserialize)]
struct MyObj {
name: String,
number: i32,
}
const MAX_SIZE: usize = 262_144; // max payload size is 256k
#[post("/")]
async fn index_manual(mut payload: web::Payload) -> Result<HttpResponse, Error> {
// payload is a stream of Bytes objects
let mut body = web::BytesMut::new();
while let Some(chunk) = payload.next().await {
let chunk = chunk?;
// limit max size of in-memory payload
if (body.len() + chunk.len()) > MAX_SIZE {
return Err(error::ErrorBadRequest("overflow"));
}
body.extend_from_slice(&chunk);
}
// body is loaded, now we can deserialize serde-json
let obj = serde_json::from_slice::<MyObj>(&body)?;
Ok(HttpResponse::Ok().json(obj)) // <- send response
}
实例文件夹中提供了这两个选项的完整示例。
分块编码
actix 对分块 编码自动解码。web::Payload
提取器已包含解码的字节流。如果请求负载是用支持的压缩编解码器(br、gzip、deflate)压缩的,则字节流将被解压缩。
Multipart 主体
actix-web 通过扩展的 crate actix-multipart
提供了 multipart 流支持。
示例文件夹中提供了完整示例。
Urlencoded 主体
actix-web 提供了对 application/x-www-form-urlencoded 编码主体的支持,其中 web::Form
提取器可解析为反序列化的实例。实例的类型必须实现 serde crate 提供的 Deserialize
trait。
在以下几种情况中,UrlEncoded future 会解析为错误:
- content-type 不是
application/x-www-form-urlencoded
。 - 传输
分块(chunked)
编码。 - content-length 大于 256k。
- 有效负载因错误而终止。
use actix_web::{post, web, HttpResponse};
use serde::Deserialize;
#[derive(Deserialize)]
struct FormData {
username: String,
}
#[post("/")]
async fn index(form: web::Form<FormData>) -> HttpResponse {
HttpResponse::Ok().body(format!("username: {}", form.username))
}
流式请求
HttpRequest 是一个字节(Bytes)
流对象,可以用来读取请求主体的有效负载。
下面的示例中,我们逐块读取并打印请求负载:
use actix_web::{get, web, Error, HttpResponse};
use futures::StreamExt;
#[get("/")]
async fn index(mut body: web::Payload) -> Result<HttpResponse, Error> {
let mut bytes = web::BytesMut::new();
while let Some(item) = body.next().await {
let item = item?;
println!("Chunk: {:?}", &item);
bytes.extend_from_slice(&item);
}
Ok(HttpResponse::Ok().finish())
}