提取器

类型安全的信息提取

Actix提供类型安全请求信息提取功能。默认情况下,actix提供了几个提取器实现。

访问提取器

如何访问Extractor取决于您使用的是处理函数还是自定义Handler类型。

在Handler函数内

提取器可以被传递到一个处理函数作为函数参数 或通过调用ExtractorType::<…>::extract(req)功能的功能范围内访问。

  1. // Option 1: passed as a parameter to a handler function
  2. fn index((params, info): (Path<(String, String,)>, Json<MyInfo>)) -> HttpResponse {
  3. ...
  4. }
  5. // Option 2: accessed by calling extract() on the Extractor
  6. use actix_web::FromRequest;
  7. fn index(req: &HttpRequest) -> HttpResponse {
  8. let params = Path::<(String, String)>::extract(req);
  9. let info = Json::<MyInfo>::extract(req);
  10. ...
  11. }

在自定义Handler类型中

与Handler函数一样,自定义Handler类型可以通过调用ExtractorType :: <...> :: extract(&req)函数来访问 Extractor。无法将Extractor 作为参数传递给自定义Handler类型,因为自定义Handler类型必须遵循handle实现的Handlertrait指定的函数签名。

  1. struct MyHandler(String);
  2. impl<S> Handler<S> for MyHandler {
  3. type Result = HttpResponse;
  4. /// Handle request
  5. fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
  6. let params = Path::<(String, String)>::extract(req);
  7. let info = Json::<MyInfo>::extract(req);
  8. ...
  9. HttpResponse::Ok().into()
  10. }
  11. }

Path

Path提供可从Request的路径中提取的信息。您可以从路径反序列化任何变量段。

例如,对于为/users/{userid}/{friend}路径注册的资源,可以对两个段进行反序列化,userid以及friend。这些片段可以被提取到一个tuple,即Path<(u32, String)>或任何Deserializeserde crate 实现trait的结构中。

  1. use actix_web::{App, Path, Result, http};
  2. /// extract path info from "/users/{userid}/{friend}" url
  3. /// {userid} - - deserializes to a u32
  4. /// {friend} - deserializes to a String
  5. fn index(info: Path<(u32, String)>) -> Result<String> {
  6. Ok(format!("Welcome {}! {}", info.1, info.0))
  7. }
  8. fn main() {
  9. let app = App::new().resource(
  10. "/users/{userid}/{friend}", // <- define path parameters
  11. |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor
  12. }

记得!必须使用Route::with() 方法注册使用提取器的处理函数 。

还可以将路径信息提取到Deserialize从serde实现特征的特定类型。这是一个使用serde 而不是元组类型的等效示例。

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

Query

可以使用请求的查询完成相同的操作。的查询 类型提供提取功能。在它下面使用serde_urlencoded箱子。

  1. #[macro_use] extern crate serde_derive;
  2. use actix_web::{App, Query, http};
  3. #[derive(Deserialize)]
  4. struct Info {
  5. username: String,
  6. }
  7. // this handler get called only if the request's query contains `username` field
  8. fn index(info: Query<Info>) -> String {
  9. format!("Welcome {}!", info.username)
  10. }
  11. fn main() {
  12. let app = App::new().resource(
  13. "/index.html",
  14. |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor
  15. }

Json

Json Json允许将请求主体反序列化为结构。要从请求的正文中提取类型信息,该类型T必须实现 serde的Deserializetrait。

  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. /// deserialize `Info` from request's body
  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. }

一些提取器提供了一种配置提取过程的方法。Json提取器 JsonConfig类型用于配置。使用时注册处理程序时Route::with(),它将返回配置实例。在Json提取器的情况下,它返回一个JsonConfig。您可以配置json有效内容的最大大小以及自定义错误处理函数。

以下示例将有效负载的大小限制为4kb,并使用自定义错误处理程序。

  1. #[macro_use] extern crate serde_derive;
  2. use actix_web::{App, Json, HttpResponse, Result, http, error};
  3. #[derive(Deserialize)]
  4. struct Info {
  5. username: String,
  6. }
  7. /// deserialize `Info` from request's body, max payload size is 4kb
  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", |r| {
  14. r.method(http::Method::POST)
  15. .with_config(index, |cfg| {
  16. cfg.limit(4096) // <- change json extractor configuration
  17. cfg.error_handler(|err, req| { // <- create custom error response
  18. error::InternalError::from_response(
  19. err, HttpResponse::Conflict().finish()).into()
  20. })
  21. });
  22. });
  23. }

Form

目前只支持url编码的表单。可以将URL编码的主体提取为特定类型。此类型必须实现serde crate中的Deserialize特征。

FormConfig允许配置提取过程。

  1. #[macro_use] extern crate serde_derive;
  2. use actix_web::{App, Form, Result};
  3. #[derive(Deserialize)]
  4. struct FormData {
  5. username: String,
  6. }
  7. /// extract form data using serde
  8. /// this handler gets called only if the content type is *x-www-form-urlencoded*
  9. /// and the content of the request could be deserialized to a `FormData` struct
  10. fn index(form: Form<FormData>) -> Result<String> {
  11. Ok(format!("Welcome {}!", form.username))
  12. }
  13. # fn main() {}

多提取器

Actix为元素实现的tuples(最多10个元素)提供了提取器实现FromRequest

例如,我们可以同时使用路径提取器和查询提取器。

  1. #[macro_use] extern crate serde_derive;
  2. use actix_web::{App, Query, Path, http};
  3. #[derive(Deserialize)]
  4. struct Info {
  5. username: String,
  6. }
  7. fn index((path, query): (Path<(u32, String)>, Query<Info>)) -> String {
  8. format!("Welcome {}!", query.username)
  9. }
  10. fn main() {
  11. let app = App::new().resource(
  12. "/users/{userid}/{friend}", // <- define path parameters
  13. |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor
  14. }

其他

Actix还提供了其他几种提取器:

  • State - 如果需要访问应用程序状态。类似 HttpRequest::state().

  • HttpRequest - HttpRequest 本身是一个提取器,它返回self,以防您需要访问请求。

  • String - 您可以将请求的有效负载转换为String.Example在doc字符串中可用。

  • bytes::Bytes - 您可以将请求的有效负载转换为字节: Bytes.Example