【问题标题】:How to return an error to caller from an actix-web handler with client?如何从带有客户端的 actix-web 处理程序向调用者返回错误?
【发布时间】:2019-09-05 13:14:38
【问题描述】:

我使用 actix_web 创建了一个服务器,它将通过 GET 连接到另一个使用 actix 客户端的服务,并在成功时返回正文或在错误时返回错误。我已经能够返回正文,但不知道如何返回错误。

这是我的处理程序:

fn echo_client(client: web::Data<Client>) -> impl Future<Item = HttpResponse, Error = Error> {
    client
        .get("127.0.0.1:9596/echo/javier") // <- Create request builder
        .header("User-Agent", "Actix-web")
        //.finish().unwrap()
        .send() // <- Send http request
        .map_err(|_| ())
        //.map_err(Error::from)
        .and_then(|response| {
            response
                .body()
                .and_then(|body| {
                    println!("{:?}", body);
                    Ok(HttpResponse::Ok().body(body))
                })
                .map_err(|error| Err(error.error_response()))
        })
}

【问题讨论】:

    标签: rust actix-web


    【解决方案1】:

    可能会失败的三件事:

    1. 连接失败。
    2. 非 200 状态代码。
    3. 体流突然停止。

    要处理 1,不 map_err 到 ():

    .map_err(|err| match err {
        SendRequestError::Connect(error) => {
            ErrorBadGateway(format!("Unable to connect to httpbin: {}", error))
        }
        error => ErrorInternalServerError(error),
    })
    

    SendRequestError 列出了在执行客户端请求时可能发生的错误。

    要处理 2,请确保使用客户端响应中的状态代码:

    .and_then(|response| Ok(HttpResponse::build(response.status()).streaming(response))))
    

    actix-web 处理 3 我相信。

    完整示例,也处理标题:

    use actix_web::client::{Client, SendRequestError};
    use actix_web::error::{ErrorBadGateway, ErrorInternalServerError};
    use actix_web::{web, App, Error, HttpResponse, HttpServer};
    use futures::future::Future;
    
    fn main() {
        HttpServer::new(|| App::new().data(Client::new()).route("/", web::to(handler)))
            .bind("127.0.0.1:8000")
            .expect("Cannot bind to port 8000")
            .run()
            .expect("Unable to run server");
    }
    
    fn handler(client: web::Data<Client>) -> Box<Future<Item = HttpResponse, Error = Error>> {
        Box::new(
            client
                .get("https://httpbin.org/get")
                .no_decompress()
                .send()
                .map_err(|err| match err {
                    SendRequestError::Connect(error) => {
                        ErrorBadGateway(format!("Unable to connect to httpbin: {}", error))
                    }
                    error => ErrorInternalServerError(error),
                })
                .and_then(|response| {
                    let mut result = HttpResponse::build(response.status());
                    let headers = response
                        .headers()
                        .iter()
                        .filter(|(h, _)| *h != "connection" && *h != "content-length");
                    for (header_name, header_value) in headers {
                        result.header(header_name.clone(), header_value.clone());
                    }
                    Ok(result.streaming(response))
                }),
        )
    }
    

    实际上失败了:

    $ curl -v localhost:8000
    * Rebuilt URL to: localhost:8000/
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Connected to localhost (127.0.0.1) port 8000 (#0)
    > GET / HTTP/1.1
    > Host: localhost:8000
    > User-Agent: curl/7.54.0
    > Accept: */*
    > 
    < HTTP/1.1 502 Bad Gateway
    < content-length: 50
    < content-type: text/plain
    < date: Sun, 07 Jul 2019 21:01:39 GMT
    < 
    * Connection #0 to host localhost left intact
    Unable to connect to httpbin: SSL is not supported
    

    在 Cargo.toml 中添加 ssl 作为功能来修复连接错误:

    actix-web = { version = "1.0", features=["ssl"] }
    

    然后再次尝试请求:

    $ curl -v localhost:8000
    * Rebuilt URL to: localhost:8000/
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Connected to localhost (127.0.0.1) port 8000 (#0)
    > GET / HTTP/1.1
    > Host: localhost:8000
    > User-Agent: curl/7.54.0
    > Accept: */*
    > 
    < HTTP/1.1 200 OK
    < transfer-encoding: chunked
    < x-frame-options: DENY
    < date: Sun, 07 Jul 2019 21:07:18 GMT
    < content-type: application/json
    < access-control-allow-origin: *
    < access-control-allow-credentials: true
    < server: nginx
    < x-content-type-options: nosniff
    < x-xss-protection: 1; mode=block
    < referrer-policy: no-referrer-when-downgrade
    < 
    {
      "args": {}, 
      "headers": {
        "Date": "Sun, 07 Jul 2019 21:07:18 GMT", 
        "Host": "httpbin.org"
      }, 
      "origin": "212.251.175.90, 212.251.175.90", 
      "url": "https://httpbin.org/get"
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-13
      • 1970-01-01
      • 2022-07-04
      • 1970-01-01
      • 2021-05-09
      • 2016-05-19
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多