我有一个使用
Rust
用 actix-web
编写的小型后端应用程序。我想要一个类似下面的功能。
async fn function(var: bool) -> impl Responder {
if var {
Redirect::to("link")
} else {
NamedFile::open_async("/file").await
}
}
我收到错误
:`if` and `else` have incompatible types expected `Redirect`, found future
。
我认为这可能可以通过将文件读入字符串并使用
HttpResponse
来完成。但既然 NamedFile
实现了 Responder
,是否有可能让它在这种设置下工作?
如果我去掉 if-else,它们都是有效的返回类型,但 if-else 语句的返回类型必须匹配。那么,在这种情况下是否可以不使用 if-else 呢?
编辑:链接的解决方案在这种情况下不起作用。将 impl Responder 更改为
Box<dyn Responder>
会导致特征边界失败。我收到以下错误消息:
the trait bound `std::boxed::Box<(dyn actix_web::Responder + 'static)>: actix_web::Responder` is not satisfied
也许它可以修复,但我没有足够的 Rust 泛型经验来做到这一点。
动态调度无法与
Responder
配合使用,但还有其他两种解决方案。
Either
,它还通过转发到活动变体来实现 Responder
:
use actix_web::Either;
async fn function(var: bool) -> impl Responder {
if var {
Either::Left(Redirect::to("link"))
} else {
Either::Right(NamedFile::open_async("/file").await)
}
}
第二个选择,正如您所说,是将它们转换为
HttpResponse
。他们有不同的体型,所以我们还需要转换体型:
async fn function(var: bool, request: HttpRequest) -> HttpResponse {
if var {
Redirect::to("link")
.respond_to(&request)
.map_into_boxed_body()
} else {
NamedFile::open_async("/file")
.await
.respond_to(&request)
.map_into_boxed_body()
}
}
HttpRequest
是一个提取器,因此您可以在处理函数中包含此参数。