Warp.rs:warp :: Reject和使用'?'进行错误处理 [英] Warp.rs: warp::Rejection and error handling using '?'

查看:140
本文介绍了Warp.rs:warp :: Reject和使用'?'进行错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 warp.rs 0.2.2 ,让我们考虑基本的Web服务,其中一个路由用于GET /:

Using warp.rs 0.2.2, let's consider a basic web service with one route for GET /:

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
    let getRoot = warp::get().and(warp::path::end()).and_then(routes::getRoot);
    warp::serve(getRoot).run(([0, 0, 0, 0], 3030)).await;
    Ok(())
}

我的目标是在路由处理程序中使用?进行错误处理,因此让我们写一个可以出错并在crate::routes早期返回的代码:

My goal is to use ? for error handling in the route handlers, so let's write one that can error and return early in crate::routes:

use crate::errors::ServiceError;
use url::Url;

pub async fn getRoot() -> Result<impl warp::Reply, warp::Rejection> {
    let _parsed_url = Url::parse(&"https://whydoesn.it/work?").map_err(ServiceError::from)?;

    Ok("Hello world !")
}

此版本有效. 在这里,Url::parse()返回的错误是url::ParseError

This version works. Here the error that's returned by Url::parse() is a url::ParseError

要在错误类型之间进行转换,从url::ParseErrorServiceError,然后从ServiceErrorwarp::Rejection,我在crate::errors中编写了一些错误帮助程序:

To convert between error types, from url::ParseError to ServiceError, then from ServiceError to warp::Rejection, I've written some error helpers in crate::errors:

#[derive(thiserror::Error, Debug)]
pub enum ServiceError {
    #[error(transparent)]
    Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error
}
impl warp::reject::Reject for ServiceError {}
impl From<ServiceError> for warp::reject::Rejection {
    fn from(e: ServiceError) -> Self {
        warp::reject::custom(e)
    }
}
impl From<url::ParseError> for ServiceError {
    fn from(e: url::ParseError) -> Self {
        ServiceError::Other(e.into())
    }
}


现在,上面的方法起作用了,并且我正在尝试缩短第二个代码块以直接使用?进行错误处理,并自动将基础错误(此处为url::ParseError)转换为warp::Rejection. 这是我尝试过的:


Now, the above works, and I'm trying to shorten the second code block to use ? for error handling directly, and convert automatically from the underlying error (here url::ParseError) to a warp::Rejection. Here's what I've tried:

use crate::errors::ServiceError;
use url::Url;

pub async fn getRoot() -> Result<impl warp::Reply, ServiceError> {
    let _parsed_url = Url::parse(&"https://whydoesn.it/work?")?;

    Ok("Hello world !")
}

Url::Parse返回的url::ParseError可以很好地转换为ServiceError以返回,但是从我的处理程序中返回ServiceError不起作用. 我得到的第一个编译错误是:

The url::ParseError returned by Url::Parse will convert fine into a ServiceError to return, but returning a ServiceError from my handler doesn't work. The first compilation error I get is:

error[E0277]: the trait bound `errors::ServiceError: warp::reject::sealed::CombineRejection<warp::reject::Rejection>` is not satisfied
   --> src/main.rs:102:54
    |
102 |     let getRoot = warp::get().and(warp::path::end()).and_then(routes::getRoot);
    |                                                      ^^^^^^^^ the trait `warp::reject::sealed::CombineRejection<warp::reject::Rejection>` is not implemented for `errors::ServiceError`

有没有一种方法可以仅使用?和以下任一方法来保持简短的错误处理:

Is there a way I can keep the short error handling using ? only and either:

  • 使ServiceError实现warp::reject::sealed::CombineRejection<warp::reject::Rejection>吗?
  • 解决这个问题吗?
  • make ServiceError implement warp::reject::sealed::CombineRejection<warp::reject::Rejection> ?
  • work around that ?

推荐答案

我已经仔细研究了一段时间.根据我的发现,有两种解决方案.

I have been looking into exactly this for a while now. From my findings there are two solutions.

1:使用一个宏,如果存在错误,该宏将构造并从中返回响应.本质上是放弃?为您自己的宏.

1: Use a macro that if there is an error constructs and returns a response from it. In essence abandon ? for your own macro.

2:使用cjbassi当前的PR#458代替以下版本的主线发布:

2: Use the current PR #458 by cjbassi instead of the mainline release by:

  • 实施warp :: reply ::答复您的错误类型,以便将其转换为正确的面向用户的错误消息.
  • 替换'warp ='0.2''在Cargo.toml文件中使用'warp = {git ="https://github.com/cjbassi/warp.git",branch ="error"}'
  • 使用.map_async代替.and_then作为处理程序

这篇关于Warp.rs:warp :: Reject和使用'?'进行错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆