简体   繁体   中英

How to deal with boxed and chained error on rust?

Il have many proxies uri (http and socks5) and i'm using reqwest for sending some http request throught theses proxies and i wanna drop a proxy if he didn't work.

for proxy in proxies {
    let proxy = match Proxy::all(proxy_url) {
        Ok(proxy) => proxy,
        Err(e) => {
            eprintln!("creating proxy failed! {:?}", e);
            continue;
        }
    };

    let client = match Client::builder()
    .proxy(proxy)
    .build()

    let client = match client {
        Ok(client) => client,
        Err(e) => {
            eprintln!("building client failed! {:?}", e);
            continue;
        }
    }

    loop {
        match client.get(&config.endpoint).send().await {
            Ok(_) => {}
            Err(e) => {
                if e.is_proxy_error() { // this method doesn't exist
                    eprintln!("Dropping proxy...");
                    break;
                } else {
                    eprintln!("client error! {:?}", e);
                }
            }
        }
    }
}

And i got many kind of Reqwest::Error

reqwest::Error { kind: Request, url: "http://example.com/", source: hyper::Error(Connect, "socks connect error: Invalid response version") }
reqwest::Error { kind: Request, url: "http://example.com/", source: hyper::Error(Connect, "socks connect error: Proxy server unreachable") }
reqwest::Error { kind: Request, url: "http://example.com/", source: hyper::Error(Connect, "socks connect error: Connection refused") }
reqwest::Error { kind: Request, url: "http://example.com/", source: hyper::Error(Connect, "socks connect error: Connection reset by peer (os error 104)") }

The error message is explicit in most case, but how can i handle each of them differently? The reqwest::Error have inner field which is private so i cant access him. And if i get the source of the reqwest::Error , i just have an Box<syn Error> which i cant treat like a hyper::Error

You can downcast the result of Error::source() to a concrete error type, eg

use std::error::Error;

...

    Err(reqwest_error) => {
        let hyper_error: Option<&hyper::Error> = reqwest_error
            .source()
            .unwrap()
            .downcast_ref();
        ...
    }

This code uses unwrap() to extract the error from the Option returned by source() . If you can't guarantee that the error will always have a source, you should use some conditional way to unwrap the source, eg

let hyper_error: Option<&hyper::Error> = reqwest_error
    .source()
    .and_then(|e| e.downcast_ref());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM