3

我有一个变量可以控制哪个函数是我的 Web 应用程序的默认行为,但这两个函数都是async并且它不会让我这样做,因为它们是不同的闭包。这样的事情会重现相同的错误: https ://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=db0269ef4852a94438e6d4925ca83d3b

现在我的问题是:

  • 我该如何解决这个问题以便匹配有效?
  • 有没有更好的方法可以根据用户 CLI 标志以编程方式在 actix 上设置默认服务器行为?对于上下文,这或多或少是我所拥有的:

main.rs

// Matches comes from the command line
let a = match matches.occurrences_of("default"){
        1 => handlers::forward,
        _ => handlers::resource_not_found,
    };

... setting up db, auth etc

HttpServer::new(move || {
            App::new()
            ... lots of routes 
            .default_service(web::route().to(a))

handlers.rs


pub async fn resource_not_found(
) -> Result<HttpResponse, Error> {
   Ok(HttpResponse::NotFound().body("Resource does not exist"))
}
pub async fn forward(
) -> Result<HttpResponse, Error> {
   Ok(HttpResponse::Ok().body("Resource does exist"))
}
4

1 回答 1

1

我该如何解决这个问题以便匹配有效

您可以创建两个闭包,它们都返回一个装箱的未来,并将它们强制为一个函数指针:

use std::pin::Pin;
use std::future::Future;

let a: fn() -> Pin<Box<dyn Future<Output = Result<HttpResponse, Error>>>> =
    match matches.occurrences_of("default") {
        1 => || Box::pin(handlers::forward()),
        _ => || Box::pin(handlers::resource_not_found()),
    };

如果功能真的那么简单,那么您可以避免装箱并返回std::future::Ready

use std::pin::Pin;
use std::future::{Future, Ready, ready};

let a: fn() -> Ready<Result<HttpResponse, Error>> =
    match matches.occurrences_of("default") {
        1 => || handlers::forward,
        _ => || handlers::resource_not_found,
    };

// handlers.rs

pub fn resource_not_found(
) -> Ready<Result<HttpResponse, Error>> {
   ready(Ok(HttpResponse::NotFound().body("Resource does not exist")))
}

pub fn forward(
) -> Ready<Result<HttpResponse, Error>> {
   ready(Ok(HttpResponse::Ok().body("Resource does exist")))
}

有没有更好的方法可以根据用户 CLI 标志在 actix 上以编程方式设置默认服务器行为

您可以在新处理程序内部而不是外部进行匹配:

let x = matches.occurrences_of("default");
let a = move || async move {
    match x {
        1 => handlers::forward().await,
        _ => handlers::resource_not_found().await,
    }
};

现在,您只需匹配一个整数,而不是每次调用的额外分配和动态调度。

于 2021-10-12T03:41:02.543 回答