rust - 如何使用客户端从 actix-web 处理程序向调用方返回错误?

标签 rust actix-web

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

这是我的处理程序:

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()))
        })
}

最佳答案

三种情况可能会失败:

  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 我相信。

完整示例,也处理 header :

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"
}

关于rust - 如何使用客户端从 actix-web 处理程序向调用方返回错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55691151/

相关文章:

rust - 如何结合 `Ord::cmp()`中的两个cmp条件

rust - 要求特征实现可以相互转换

rust - 有没有办法让 serde_json 严格反序列化?

Rust actix-web 线程不安全移动

linux - 添加了对mongodb的异步调用后,带有mongodb项目的actix Web无法构建

asynchronous - 使用 Rust actix-web 流式传输结果,生命周期问题

rust - 如何减少可变范围

Rust 模式与现有绑定(bind)匹配?

rust - 这#行代码在 Rust 中意味着什么?

linux - 错误 "/lib/x86_64-linux-gnu/libc.so.6: version ` GLIBC_2.3 3' not found"