从异步方法返回并使用 reqwest::Response

问题描述 投票:0回答:1

我希望通过添加在响应为 401 时捕获、重新验证和重试的逻辑来改进一些为

reqwest::Response
制作和返回 Future 的逻辑。但是,即使在我开始重试逻辑之前,我的尝试将
reqwest::Response
的创建移至异步方法(将在其中放置重新验证逻辑)会因生命周期错误而失败。

要替换的原始工作代码是结构体中的非异步方法,返回装箱的 future;

self.Client
是一个
reqwest::Client
并且该项目正在使用 tokio 运行时:

    pub fn demo_good(
        &mut self,
        url: Url,
    ) -> Pin<Box<dyn futures::Future<Output = Result<Response, Error>> + Send>> {
        let mut map = HashMap::new();
        map.insert("fake_key".to_string(), "fake_value".to_string());
        let response = self.client.post(url).json(&map).send();
        Box::pin(response)
    }

但是,一旦我尝试开始将

self.client.post(...)...
逻辑移动到结构的异步方法中,我就会收到生命周期错误:

    // POST to the execute_url, handling reauthentication
    async fn demo_post(
        &mut self,
        url: Url,
        body: HashMap<String, String>,
    ) -> Result<Response, Error> {
        // Run first request
        let response = self.client.post(url).json(&body).send().await;
        // Todo: catch 401s, reauth, and repeat
        dbg!(&response);
        // Return
        response
    }

    pub fn demo_bad(
        &mut self,
        url: Url,
    ) -> Pin<Box<dyn futures::Future<Output = Result<Response, Error>> + Send>> {
        let mut map = HashMap::new();
        map.insert("fake_key".to_string(), "fake_value".to_string());
        let response = self.demo_post(url, map);
        Box::pin(response)
    }
   Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
  --> src/lib.rs:41:9
   |
35 |         &mut self,
   |         - let's call the lifetime of this reference `'1`
...
41 |         Box::pin(response)
   |         ^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
   |
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
   |
37 |     ) -> Pin<Box<dyn futures::Future<Output = Result<Response, Error>> + Send + '_>> {
   |                                                                    

我可以遵循这里的建议,但这并没有“实际上”从参数 self 中捕获比原始工作

demo_good
方法更多的数据。此外,我实际上确实想返回这个未来的响应以在代码库的其他地方使用,并且我担心新的生命周期约束只会进一步解决问题,导致像
error[E0515]: cannot return value referencing temporary value
这样的错误,这是我以前没有的。
是否有其他方法可以使这样的策略发挥作用,也许可以通过在某些方法签名中指定生命周期参数?或者它注定会失败,因为原始的 reqwest 方法(非异步并返回 Futures)和我添加的包装器方法(异步)之间的差异,并且有一些不同的设计可供使用?

这里是 Rust 游乐场中此代码的链接:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5e92c7a6977c2a4cdaa51dae7419c266

asynchronous rust lifetime rust-tokio reqwest
1个回答
0
投票
impl Trait

而不是

async fn
来说服编译器:
// POST to the execute_url, handling reauthentication
fn demo_post(
    &mut self,
    url: Url,
    body: HashMap<String, String>,
) -> impl Future<Output = Result<Response, Error>> {
    let request = self.client.post(url);
    async move {
        // Run first request
        let response = request.json(&body).send().await;
        // Todo: catch 401s, reauth, and repeat
        dbg!(&response);
        // Return
        response
    }
}

	
© www.soinside.com 2019 - 2024. All rights reserved.