add error handling

This commit is contained in:
Jan Kantert 2020-05-03 13:18:09 +02:00 committed by Felipe Noronha
parent d838516387
commit 55103945a7

View File

@ -34,7 +34,7 @@
//! //!
//! ```rust,no_run //! ```rust,no_run
//! use hyper::server::conn::AddrStream; //! use hyper::server::conn::AddrStream;
//! use hyper::{Body, Request, Response, Server}; //! use hyper::{Body, Request, Response, Server, StatusCode};
//! use hyper::service::{service_fn, make_service_fn}; //! use hyper::service::{service_fn, make_service_fn};
//! use futures::future::{self, Future}; //! use futures::future::{self, Future};
//! use std::{convert::Infallible, net::SocketAddr}; //! use std::{convert::Infallible, net::SocketAddr};
@ -49,13 +49,23 @@
//! async fn handle(client_ip: IpAddr, req: Request<Body>) -> Result<Response<Body>, Infallible> { //! async fn handle(client_ip: IpAddr, req: Request<Body>) -> Result<Response<Body>, Infallible> {
//! if req.uri().path().starts_with("/target/first") { //! if req.uri().path().starts_with("/target/first") {
//! // will forward requests to port 13901 //! // will forward requests to port 13901
//! Ok(hyper_reverse_proxy::call(client_ip, "http://127.0.0.1:13901", req).await.unwrap()) //! match hyper_reverse_proxy::call(client_ip, "http://127.0.0.1:13901", req).await {
//! //! Ok(response) => {Ok(response)}
//! Err(error) => {Ok(Response::builder()
//! .status(StatusCode::INTERNAL_SERVER_ERROR)
//! .body(Body::empty())
//! .unwrap())}
//! }
//! } else if req.uri().path().starts_with("/target/second") { //! } else if req.uri().path().starts_with("/target/second") {
//! //!
//! // will forward requests to port 13902 //! // will forward requests to port 13902
//! Ok(hyper_reverse_proxy::call(client_ip, "http://127.0.0.1:13902", req).await.unwrap()) //! match hyper_reverse_proxy::call(client_ip, "http://127.0.0.1:13902", req).await {
//! //! Ok(response) => {Ok(response)}
//! Err(error) => {Ok(Response::builder()
//! .status(StatusCode::INTERNAL_SERVER_ERROR)
//! .body(Body::empty())
//! .unwrap())}
//! }
//! } else { //! } else {
//! debug_request(req) //! debug_request(req)
//! } //! }
@ -85,12 +95,43 @@
//! //!
use hyper::header::{HeaderMap, HeaderValue}; use hyper::header::{HeaderMap, HeaderValue};
use hyper::http::header::{InvalidHeaderValue, ToStrError};
use hyper::http::uri::InvalidUri; use hyper::http::uri::InvalidUri;
use hyper::{Body, Client, Request, Response, StatusCode, Uri}; use hyper::{Body, Client, Error, Request, Response, Uri};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::net::IpAddr; use std::net::IpAddr;
use std::str::FromStr; use std::str::FromStr;
pub enum ProxyError {
InvalidUri(InvalidUri),
HyperError(Error),
ForwardHeaderError,
}
impl From<Error> for ProxyError {
fn from(err: Error) -> ProxyError {
ProxyError::HyperError(err)
}
}
impl From<InvalidUri> for ProxyError {
fn from(err: InvalidUri) -> ProxyError {
ProxyError::InvalidUri(err)
}
}
impl From<ToStrError> for ProxyError {
fn from(_err: ToStrError) -> ProxyError {
ProxyError::ForwardHeaderError
}
}
impl From<InvalidHeaderValue> for ProxyError {
fn from(_err: InvalidHeaderValue) -> ProxyError {
ProxyError::ForwardHeaderError
}
}
fn is_hop_header(name: &str) -> bool { fn is_hop_header(name: &str) -> bool {
use unicase::Ascii; use unicase::Ascii;
@ -144,7 +185,7 @@ fn create_proxied_request<B>(
client_ip: IpAddr, client_ip: IpAddr,
forward_url: &str, forward_url: &str,
mut request: Request<B>, mut request: Request<B>,
) -> Result<Request<B>, InvalidUri> { ) -> Result<Request<B>, ProxyError> {
*request.headers_mut() = remove_hop_headers(request.headers()); *request.headers_mut() = remove_hop_headers(request.headers());
*request.uri_mut() = forward_uri(forward_url, &request)?; *request.uri_mut() = forward_uri(forward_url, &request)?;
@ -153,12 +194,12 @@ fn create_proxied_request<B>(
// Add forwarding information in the headers // Add forwarding information in the headers
match request.headers_mut().entry(x_forwarded_for_header_name) { match request.headers_mut().entry(x_forwarded_for_header_name) {
hyper::header::Entry::Vacant(entry) => { hyper::header::Entry::Vacant(entry) => {
entry.insert(client_ip.to_string().parse().unwrap()); entry.insert(client_ip.to_string().parse()?);
} }
hyper::header::Entry::Occupied(mut entry) => { hyper::header::Entry::Occupied(mut entry) => {
let addr = format!("{}, {}", entry.get().to_str().unwrap(), client_ip); let addr = format!("{}, {}", entry.get().to_str()?, client_ip);
entry.insert(addr.parse().unwrap()); entry.insert(addr.parse()?);
} }
} }
@ -169,20 +210,11 @@ pub async fn call(
client_ip: IpAddr, client_ip: IpAddr,
forward_uri: &str, forward_uri: &str,
request: Request<Body>, request: Request<Body>,
) -> Result<Response<Body>, InvalidUri> { ) -> Result<Response<Body>, ProxyError> {
let proxied_request = create_proxied_request(client_ip, &forward_uri, request)?; let proxied_request = create_proxied_request(client_ip, &forward_uri, request)?;
let client = Client::new(); let client = Client::new();
let response = client.request(proxied_request).await; let response = client.request(proxied_request).await?;
let proxied_response = match response { let proxied_response = create_proxied_response(response);
Ok(response) => create_proxied_response(response),
Err(error) => {
println!("Error: {}", error); // TODO: Configurable logging
Response::builder()
.status(StatusCode::SERVICE_UNAVAILABLE)
.body(Body::empty())
.unwrap()
}
};
Ok(proxied_response) Ok(proxied_response)
} }