actix_proxy/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use actix_web::http::StatusCode;
4use actix_web::{dev, HttpResponse, ResponseError};
5
6use awc::error::{
7  ConnectError, SendRequestError as AwcSendRequestError,
8};
9use awc::ClientResponse;
10
11use std::fmt;
12
13/// Wrapper around awc's [`SendRequestError`] implementing
14/// [`actix_web::ResponseError`].
15///
16/// [`SendRequestError`]: AwcSendRequestError
17/// [`actix_web::ResponseError`]: ResponseError
18///
19#[derive(Debug)]
20pub struct SendRequestError(AwcSendRequestError);
21
22impl fmt::Display for SendRequestError {
23  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24    write!(f, "{}", self.0)
25  }
26}
27
28impl From<AwcSendRequestError> for SendRequestError {
29  fn from(e: AwcSendRequestError) -> Self {
30    Self(e)
31  }
32}
33
34/// Convert `SendRequestError` to a server `Response`
35///
36impl ResponseError for SendRequestError {
37  fn status_code(&self) -> StatusCode {
38    match self.0 {
39      AwcSendRequestError::Connect(ConnectError::Timeout) => {
40        StatusCode::GATEWAY_TIMEOUT
41      }
42      AwcSendRequestError::Connect(_) => StatusCode::BAD_REQUEST,
43      _ => StatusCode::INTERNAL_SERVER_ERROR,
44    }
45  }
46}
47
48/// Trait for converting a [`ClientResponse`] into a [`HttpResponse`].
49///
50/// You can implement this trait on your types, of course, but its
51/// main goal is to enable [`ClientResponse`] as return value in
52/// [`impl Responder`](actix_web::Responder) contexts.
53///
54/// [`ClientResponse`]: ClientResponse
55/// [`HttpResponse`]: HttpResponse
56///
57pub trait IntoHttpResponse {
58  /// Creates a [`HttpResponse`] from `self`.
59  ///
60  /// [`HttpResponse`]: HttpResponse
61  ///
62  fn into_http_response(self) -> HttpResponse;
63
64  /// Wraps the [`HttpResponse`] created by [`into_http_response`]
65  /// in a `Result`.
66  ///
67  /// # Errors
68  ///
69  /// Because [`into_http_response`] is infallible, this method is,
70  /// too.
71  /// So calling this method never fails and never returns an `Err`.
72  ///
73  /// [`HttpResponse`]: HttpResponse
74  /// [`into_http_response`]: Self::into_http_response
75  ///
76  fn into_wrapped_http_response<E>(self) -> Result<HttpResponse, E>
77  where
78    Self: Sized,
79  {
80    Ok(self.into_http_response())
81  }
82}
83
84impl IntoHttpResponse
85  for ClientResponse<dev::Decompress<dev::Payload>>
86{
87  fn into_http_response(self) -> HttpResponse {
88    let mut response = HttpResponse::build(self.status());
89
90    self.headers().into_iter().for_each(|(k, v)| {
91      response.insert_header((k, v));
92    });
93
94    response.streaming(self)
95  }
96}