6

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-web并且actix-web-codegen docs没有找到任何解决这个问题的方法

4

3 回答 3

7

你可以做

#[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
}
于 2021-01-03T14:26:30.523 回答
5

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

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
}
于 2021-01-08T09:24:26.687 回答
-2

我假设您正在使用actix-web: 2.0.0withactix-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(),
    }))
}
于 2020-08-09T10:35:38.150 回答