Requests 请求

Content Encoding 内容编码

Actix-web自动解压payloads。支持以下编解码器:

  • Brotli
  • Chunked
  • Compress
  • Gzip
  • Deflate
  • Identity
  • Trailers
  • EncodingExt

如果headers包含Content-Encoding header,则将根据header值对请求payload进行解压缩。不支持多种编解码器,即:Content-Encoding: br, gzip

JSON Request

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,则将字节流解压缩。

Multipart body 多body

Actix-web通过外部crate, actix-multipart提供multipart stream(流)支持。

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

Urlencoded body

Actix-web使用web::Form提取程序为反序列化实例解析的*application/x-www-form-urlencoded*编码bodies提供支持。实例的类型必须实现*serde*的Deserialize trait。

*UrlEncoded*的将来可能会在多种情况下解决错误:

  • content type 不是 application/x-www-form-urlencoded
  • transfer encoding 是 chunked.
  • content-length 大于 256k
  • payload 因错误而终止。
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))
}

Streaming request 流请求

*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())
}
接下来: Responses 响应