请求

Actix自动解压缩有效负载。支持以下编解码器:

  • Brotli
  • Gzip
  • Deflate
  • Identity

如果请求标头包含Content-Encoding标头,则根据标头值解压缩请求有效负载。不支持多个编解码器,即:Content-Encoding: br, gzip

JSON请求

json正文反序列化有几种选择。

第一种选择是使用Json提取器。首先,定义一个Json<T>作为参数接受的处理函数,然后使用该.with()方法注册此处理程序。通过使用serde_json::Value作为类型,也可以接受任意有效的json对象T

  1. #[macro_use] extern crate serde_derive;
  2. use actix_web::{App, Json, Result, http};
  3. #[derive(Deserialize)]
  4. struct Info {
  5. username: String,
  6. }
  7. /// extract `Info` using serde
  8. fn index(info: Json<Info>) -> Result<String> {
  9. Ok(format!("Welcome {}!", info.username))
  10. }
  11. fn main() {
  12. let app = App::new().resource(
  13. "/index.html",
  14. |r| r.method(http::Method::POST).with(index)); // <- use `with` extractor
  15. }

另一种选择是使用 HttpRequest::json()。此方法返回一个JsonBody对象,该对象解析为反序列化的值。

  1. #[derive(Debug, Serialize, Deserialize)]
  2. struct MyObj {
  3. name: String,
  4. number: i32,
  5. }
  6. fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
  7. req.json().from_err()
  8. .and_then(|val: MyObj| {
  9. println!("model: {:?}", val);
  10. Ok(HttpResponse::Ok().json(val)) // <- send response
  11. })
  12. .responder()
  13. }

您也可以手动将有效负载加载到内存中,然后对其进行反序列化。

在下面的示例中,我们将反序列化MyObj结构。我们需要先加载请求体,然后将json反序列化为一个对象。

  1. extern crate serde_json;
  2. use futures::{Future, Stream};
  3. #[derive(Serialize, Deserialize)]
  4. struct MyObj {name: String, number: i32}
  5. fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
  6. // `concat2` will asynchronously read each chunk of the request body and
  7. // return a single, concatenated, chunk
  8. req.concat2()
  9. // `Future::from_err` acts like `?` in that it coerces the error type from
  10. // the future into the final error type
  11. .from_err()
  12. // `Future::and_then` can be used to merge an asynchronous workflow with a
  13. // synchronous workflow
  14. .and_then(|body| {
  15. let obj = serde_json::from_slice::<MyObj>(&body)?;
  16. Ok(HttpResponse::Ok().json(obj))
  17. })
  18. .responder()
  19. }

示例目录中提供了这两个选项的完整示例 。

分块传输编码

Actix自动解码分块编码。HttpRequest::payload()已经包含解码的字节流。如果使用所支持的压缩编解码器之一(br,gzip,deflate)压缩请求有效负载,则解压缩字节流。

Multipart

Actix提供multipart stream支持。 Multipart实现为multipart itemsEach item可以是 Field或嵌套的 Multipart流HttpResponse::multipart()返回当前请求的Multipart流。

下面演示了一个简单表单的Multipart流处理:

  1. use actix_web::*;
  2. fn index(req: &HttpRequest) -> Box<Future<...>> {
  3. // get multipart and iterate over multipart items
  4. req.multipart()
  5. .and_then(|item| {
  6. match item {
  7. multipart::MultipartItem::Field(field) => {
  8. println!("==== FIELD ==== {:?} {:?}",
  9. field.headers(),
  10. field.content_type());
  11. Either::A(
  12. field.map(|chunk| {
  13. println!("-- CHUNK: \n{}",
  14. std::str::from_utf8(&chunk).unwrap());})
  15. .fold((), |_, _| result(Ok(()))))
  16. },
  17. multipart::MultipartItem::Nested(mp) => {
  18. Either::B(result(Ok(())))
  19. }
  20. }
  21. })
  22. }

示例目录中提供了完整示例 。

Urlencoded

Actix为application / x-www-form-urlencoded编码体提供支持。 HttpResponse::urlencoded()返回UrlEncoded future,它将解析为反序列化的实例。实例的类型必须实现serde的 Deserialize特征。

在几种情况下,UrlEncoded的future可以解决为错误:

  • 内容类型不是 application/x-www-form-urlencoded
  • 传输编码是 chunked.
  • content-length大于256k
  • payload以错误终止。
  1. #[macro_use] extern crate serde_derive;
  2. use actix_web::*;
  3. use futures::future::{Future, ok};
  4. #[derive(Deserialize)]
  5. struct FormData {
  6. username: String,
  7. }
  8. fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
  9. req.urlencoded::<FormData>() // <- get UrlEncoded future
  10. .from_err()
  11. .and_then(|data| { // <- deserialized instance
  12. println!("USERNAME: {:?}", data.username);
  13. ok(HttpResponse::Ok().into())
  14. })
  15. .responder()
  16. }
  17. # fn main() {}

Streaming 请求

HttpRequest 是一个Bytes对象流。它可用于读取请求主体有效负载。

在下面的示例中,我们按块读取并打印请求有效负载块:

  1. use actix_web::*;
  2. use futures::{Future, Stream};
  3. fn index(req: &HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
  4. req
  5. .payload()
  6. .from_err()
  7. .fold((), |_, chunk| {
  8. println!("Chunk: {:?}", chunk);
  9. result::<_, error::PayloadError>(Ok(()))
  10. })
  11. .map(|_| HttpResponse::Ok().finish())
  12. .responder()
  13. }