如何在 Actix-Web 中为多个方法使用路由属性宏

How to use routes attributes macros for multiple methods in Actix-Web

Actix Web Framework中,如何使用路由属性宏(#[http_method("route")])将多个http方法绑定到一个函数?

例如,我有这个简单的端点:

/// Returns a UUID4.
#[get("/uuid")]
async fn uuid_v4() -> impl Responder {
    HttpResponse::Ok().json(Uuid {
        uuid: uuid::Uuid::new_v4(),
    })
}

我想要相同的端点处理 HEAD 请求,我该怎么做? 我最初的方法是只叠加宏:

/// Returns a UUID4.
#[get("/uuid")]
#[head("/uuid")]
async fn uuid_v4() -> impl Responder {
    HttpResponse::Ok().json(Uuid {
        uuid: uuid::Uuid::new_v4(),
    })
}

但是我确实遇到编译错误:

    |
249 | async fn uuid_v4() -> impl Responder {
    |          ^^^^^^^ the trait `actix_web::handler::Factory<_, _, _>` is not implemented for `<uuid_v4 as actix_web::service::HttpServiceFactory>::register::uuid_v4`

我已经浏览了 actix-webactix-web-codegen docs,但没有找到解决此问题的任何内容

我假设您将 actix-web: 2.0.0actix-rt: 1.0.0 一起使用,并且您正在将此处理程序传递给 App.service 方法,如下所示

HttpServer::new(move || {
            App::new()
                .wrap(middleware::Logger::default())
                .service(index)
        })
        .bind(("127.0.0.1", self.port))?
        .workers(8)
        .run()
        .await

那么你将需要像这样编写处理程序 ->

/// Returns a UUID4.
#[get("/uuid")]
async fn uuid_v4(req: HttpRequest) -> Result<web::Json<IndexResponse>> {
    let uuid_header = req
        .headers()
        .get("uuid")
        .and_then(|v| v.to_str().ok())
        .unwrap_or_else(|| "some-id");
    //curl -H "uuid: username" localhost:8080

    println!("make use of {}", uuid_header);
    Ok(web::Json(Uuid {
        uuid: uuid::Uuid::new_v4(),
    }))
}

你可以做到

#[route("/", method="GET", method="POST", method="PUT")]
async fn index() -> impl Responder {
  HttpResponse::Ok().body("Hello world!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
  HttpServer::new(move || {
    App::new()
        .service(index)
  })
  .bind("127.0.0.1:8080")?
  .run()
  .await
}

一个资源有多个路径和多个方法的示例

async fn index() -> impl Responder {
  HttpResponse::Ok().body("Hello world!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
  HttpServer::new(move || {
    App::new()
        .service(
            actix_web::web::resource(vec!["/", "/index"])
                .route(actix_web::web::get().to(index))
                .route(actix_web::web::post().to(index))
            )
  })
  .bind("127.0.0.1:8080")?
  .run()
  .await
}