URL 调度提供了简便的方式以进行简单的模式匹配,将 URL 映射到 handler 代码。如果请求相关联的路径信息与一个模式匹配,则调用特定的 handler 对象。

请求 handler 是一个函数,它接受可以从请求中提取的零个或多个参数(即 impl FromRequest),并返回可以转换为 HttpResponse(即 impl Responder)的类型。

资源配置

资源配置的作用是向应用程序添加新的资源。资源有用于 URL 生成的标识符作为名称,该名称允许开发人员向现有资源添加路由。资源也具有模式,用于匹配 URL 的部分路径(PATH),即 scheme 和 port 之后的路径部分(如 URL http://localhost:8080/foo/bar?q=value 中的 /foo/bar 部分)。但不匹配路径中的查询(QUERY),即 ? 后面的部分(如 http://localhost:8080/foo/bar?q=value 中的 q=value)。

App::route() 方法提供了简便的方式以便于注册路由。此方法用于向应用程序的路由表添加路由,并且接受路径模式、HTTP 方法,以及 handler 函数。对于相同的资源路径,可以多次调用 route() 方法,在这种情况下,多个路由注册为同一个资源路径。

use actix_web::{web, App, HttpResponse, HttpServer};async fn index() -> HttpResponse {    HttpResponse::Ok().body("Hello")}#[actix_web::main]async fn main() -> std::io::Result {    HttpServer::new(|| {        App::new()            .route("/", web::get().to(index))            .route("/user", web::post().to(index))    })    .bind("127.0.0.1:8080")?    .run()    .await}

尽管 App::route() 方法提供了简便的方式以便于注册路由,但要访问完整的资源配置,必须使用不同的方法。App::service() 方法将单个资源添加到应用程序的路由表中,该方法接受路径模式、卫语句(guards),以及一个或多个路由。

use actix_web::{guard, web, App, HttpResponse};fn index() -> HttpResponse {    HttpResponse::Ok().body("Hello")}pub fn main() {    App::new()        .service(web::resource("/prefix").to(index))        .service(            web::resource("/user/{name}")                .name("user_detail")                .guard(guard::Header("content-type", "application/json"))                .route(web::get().to(|| HttpResponse::Ok()))                .route(web::put().to(|| HttpResponse::Ok())),        );}

如果资源不包含任何路由,或没有任何匹配的路由,将返回 NOT FOUND HTTP 响应。

路由配置

资源包含一系列路由。每个路由依次有一组 卫语句(guards) 和一个 handler。可以使用 Resource::route() 方法创建新路由,该方法返回对新路由 Route 实例的引用。默认情况下,路由不包含任何卫语句,因此可以匹配所有请求,其默认 handler 为 HttpNotFound。

基于资源注册与路由注册期间定义的路由标准,应用程序的路由传入请求。应用程序根据在资源注册和路由注册期间定义的路由条件路由传入的请求。根据 Resource::route() 方法注册路由的顺序,资源匹配它包含的所有路由。

路由 Route 可含有任意多的卫语句(guards), 但只能有一个 handler。

App::new().service(    web::resource("/path").route(        web::route()            .guard(guard::Get())            .guard(guard::Header("content-type", "text/plain"))            .to(|| HttpResponse::Ok()),    ),)

在这个示例中,如果 GET 请求包含 Content-Type 标头,则返回 HttpResponse::Ok()。此标头的值为 text/plain,路径为 /path。

如果资源无法匹配任何路由,则返回 “NOT FOUND” 响应。

ResourceHandler::route() 返回路由(Route)对象。可以使用类似于 builder 的模式来配置路由。可用配置方法如下:

  • Route::guard() 注册一个新的卫语句(guard),每个路由可以注册任意数量的卫语句(guard)。
  • Route::method() 注册一个方法作为卫语句(guard),每个路由可以注册任意数量的卫语句(guard)。
  • Route::to() 为路由注册一个异步 handler 函数,仅能注册一个 handler。通常 handler 注册是最后一个配置操作。

路由匹配

路由配置的主要目的是根据 URL 路径模式去匹配(或不匹配)请求的路径(path)。路径(path)表示被请求 URL 的路径部分。

actix-web 中,路由配置的方法非常简单。当请求进入系统时,将自身向系统中的每个资源配置予以声明,actix 会根据声明的模式去检查请求的路径。根据 App::service() 方法所声明路由的顺序,检查工作依次进行。如果未找到资源,则匹配的资源为默认资源。

当路由配置被声明时,可以包含路由卫语句参数。在检查期间,对于给定请求的路由配置来说,其与路由声明关联的所有路由卫语句都必须为 true。在检查期间,如果在提供给路由配置的路由卫语句参数集合中,有任意一个卫语句返回 false,则跳过该路由。然后,根据有序的路由集合,路由匹配将继续进行。

如果匹配到任何路由,则停止路由匹配进程,并调用与该路由关联的 handler。如果在用尽所有路由模式后,仍然没有路由匹配,则返回 NOT FOUND 响应。