add error handling
This commit is contained in:
parent
d838516387
commit
55103945a7
76
src/lib.rs
76
src/lib.rs
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user