Actix-web自动解压payloads。支持以下编解码器:
如果headers包含Content-Encoding
header,则将根据header值对请求payload进行解压缩。不支持多种编解码器,即:Content-Encoding: br, gzip
。
json body反序列化有几种选择。
第一种选择是使用*Json*提取器。
首先,您定义一个接受Json<T>
作为参数的handler函数,然后,使用.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_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().route("/", web::post().to(index)))
.bind("127.0.0.1:8088")?
.run()
.await
}
您也可以将payload手动加载到内存中,然后反序列化。
在下面的示例中,我们将反序列化*MyObj*结构。我们需要先加载请求body,然后将json反序列化为一个对象。
use actix_web::{error, web, App, Error, HttpResponse};
use bytes::BytesMut;
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
async fn index_manual(mut payload: web::Payload) -> Result<HttpResponse, Error> {
// payload is a stream of Bytes objects
let mut body = 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自动解码chunked(分块)编码。
web::Payload
提取器已经包含解码后的字节流。
如果使用支持的压缩编解码器(br,gzip,deflate)之一压缩请求payload,则将字节流解压缩。
Actix-web通过外部crate, actix-multipart
提供multipart stream(流)支持。
示例目录中提供了完整的示例。
Actix-web使用web::Form
提取程序为反序列化实例解析的*application/x-www-form-urlencoded*编码bodies提供支持。实例的类型必须实现*serde*的Deserialize
trait。
*UrlEncoded*的将来可能会在多种情况下解决错误:
application/x-www-form-urlencoded
chunked
.use actix_web::{web, HttpResponse};
use serde::Deserialize;
#[derive(Deserialize)]
struct FormData {
username: String,
}
async fn index(form: web::Form<FormData>) -> HttpResponse {
HttpResponse::Ok().body(format!("username: {}", form.username))
}
*HttpRequest*是Bytes
对象的流。它可用于读取请求body payload。
在以下示例中,我们逐块读取和打印请求的payload:
use actix_web::{web, Error, HttpResponse};
use futures::StreamExt;
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())
}