rust - 将域结果映射到 http 结果
问题描述
我正在尝试在 Rust 中使用 Actix Web 框架构建 HTTP 服务器。我习惯于将业务模型和业务错误与 HttpResponse 分开。为此,我有我的服务 CredentialService,它公开了一个返回结果的方法Result<String, CredentialServiceError>
。
我的 WebServer 公开了一个POST /login
接受username
和password
返回 JWT 的 API。
枚举“CredentialServiceError”如下
use derive_more::{Display, Error};
#[derive(Debug, Display, Error)]
pub enum CredentialServiceError {
NoCredentialFound,
ErrorOnGeneratingJWT,
}
我的处理程序是这样的:
async fn login(request_body: web::Json<LoginRequest>, credential_service: web::Data<CredentialService>) -> Result<HttpResponse> {
let request_body: LoginRequest = request_body.0;
let jwt = credential_service.login(request_body.username, request_body.password);
let response: Result<LoginResponse, CredentialServiceError> = jwt.map(|jwt| {
LoginResponse { jwt }
});
response.into()
}
我收到此错误:
the trait bound `std::result::Result<actix_web::HttpResponse, actix_web::Error>: std::convert::From<std::result::Result<model::LoginResponse, credential_service::CredentialServiceError>>` is not satisfied
the trait `std::convert::From<std::result::Result<model::LoginResponse, credential_service::CredentialServiceError>>` is not implemented for `std::result::Result<actix_web::HttpResponse, actix_web::Error>`
help: the following implementations were found:
<std::result::Result<(), idna::uts46::Errors> as std::convert::From<idna::uts46::Errors>>
<std::result::Result<(), ring::error::Unspecified> as std::convert::From<ring::bssl::Result>>
<std::result::Result<miniz_oxide::MZStatus, miniz_oxide::MZError> as std::convert::From<&miniz_oxide::StreamResult>>
<std::result::Result<miniz_oxide::MZStatus, miniz_oxide::MZError> as std::convert::From<&miniz_oxide::StreamResult>>
and 2 others
note: required because of the requirements on the impl of `std::convert::Into<std::result::Result<actix_web::HttpResponse, actix_web::Error>>` for `std::result::Result<model::LoginResponse, credential_service::CredentialServiceError>`rustc(E0277)
我也尝试过实施
impl error::ResponseError for CredentialServiceError { ... }
impl Into<HttpResponse> for LoginResponse { ... }
错误没有改变。
那么,我怎样才能转换Result<String, CredentialServiceError>
成Result<HttpResponse>
?
解决方案
因此,您面临的问题是,您希望将结果转换为 actix_web 函数期望的结果。我希望我理解正确。
除了将您的结果映射到预期的结果之外,我没有看到其他方法。有不同的方法可以实现这一点。如果你想在你的LoginResponse
结构中保留实现细节,你可以使用Into特征。
impl Into<HttpResponse> for LoginResponse {
fn into(self) -> HttpResponse {
HttpResponse::Ok().body(self.jwt)
}
}
如果您不在乎,可以使用提供的地图功能Result
。
fn map_credential_error(error: CredentialServiceError) -> actix_web::error::Error {
match error {
CredentialServiceError::NoCredentialFound => {
actix_web::error::ErrorUnauthorized("Not authorized")
}
CredentialServiceError::ErrorOnGeneratingJWT => {
actix_web::error::ErrorInternalServerError("Something went wrong generating your jwt")
}
}
}
所以最后你的登录功能看起来像这样。
async fn login(
request_body: web::Json<LoginRequest>,
credential_service: web::Data<CredentialService>,
) -> Result<HttpResponse> {
let request_body: LoginRequest = request_body.0;
let jwt = credential_service.login(request_body.username, request_body.password);
let response: Result<HttpResponse, CredentialServiceError> =
jwt.map(|jwt| LoginResponse { jwt }.into());
response.map_err(map_credential_error)
}
希望我能提供帮助,并且我理解你的问题。
推荐阅读
- python - Python DBF:如何将 .cdx 索引与 .dbf 表关联
- algorithm - 在不访问键值计数的情况下将键值对分成相等的列表
- c# - 重用多个控件 (UWP) 中常见的 xaml 绑定和行为
- scala - Spark 数据框无选择
- timer - WebSphere EJB 计时器
- python - 创建具有不同大小列表的数据框
- qualtrics - 如何有条件地将文本框添加到 Qualtrics 调查中的答案
- aem - AEM 6.x:如何临时/以编程方式禁用链接检查器?(尝试返回带有链接的 JSON 返回浏览器)
- vagrant - Laravel Homestead/Vagrant/Virtualbox 在 Windows 上运行缓慢
- php - 显示添加到网站目录的最新文件,同时排除 PHP 中的某些特定文件