Improve error handling
This commit is contained in:
parent
06bf4d9afb
commit
060d47cbcc
1 changed files with 46 additions and 22 deletions
68
src/main.rs
68
src/main.rs
|
@ -1,5 +1,5 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use hyper::{service::{make_service_fn, service_fn}, Error, Server, Response, StatusCode, Body, Request, Uri, client::HttpConnector};
|
use hyper::{service::{make_service_fn, service_fn}, Server, Response, StatusCode, Body, Request, Uri, client::HttpConnector, http};
|
||||||
|
|
||||||
pub mod parse;
|
pub mod parse;
|
||||||
|
|
||||||
|
@ -60,8 +60,7 @@ async fn main() {
|
||||||
// circuit).
|
// circuit).
|
||||||
let res = Response::builder()
|
let res = Response::builder()
|
||||||
.status(StatusCode::BAD_GATEWAY)
|
.status(StatusCode::BAD_GATEWAY)
|
||||||
.body(Body::empty())
|
.body(Body::empty())?;
|
||||||
.expect("Failed to construct response");
|
|
||||||
|
|
||||||
Ok (res)
|
Ok (res)
|
||||||
|
|
||||||
|
@ -118,6 +117,33 @@ pub fn parse (data: String) -> Config {
|
||||||
|
|
||||||
Config (rules)
|
Config (rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runtime errors.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Hyper (hyper::Error),
|
||||||
|
Http (http::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::Hyper (e) => e.fmt(f),
|
||||||
|
Error::Http (e) => e.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hyper::Error> for Error {
|
||||||
|
fn from (v: hyper::Error) -> Self { Self::Hyper(v) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<http::Error> for Error {
|
||||||
|
fn from (v: http::Error) -> Self { Self::Http(v) }
|
||||||
|
}
|
||||||
|
|
||||||
/// A rule consists of a [`Pattern`] and an [`Effect`]. If the pattern matches,
|
/// A rule consists of a [`Pattern`] and an [`Effect`]. If the pattern matches,
|
||||||
/// the effect is performed.
|
/// the effect is performed.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -204,39 +230,37 @@ pub enum Effect {
|
||||||
|
|
||||||
impl Effect {
|
impl Effect {
|
||||||
/// Perform the effect.
|
/// Perform the effect.
|
||||||
pub async fn perform (&self, client: Client, mut req: Request<Body>) -> hyper::Result<Response<Body>> {
|
pub async fn perform (&self, client: Client, mut req: Request<Body>) -> Result<Response<Body>, Error> {
|
||||||
match self {
|
let res = match self {
|
||||||
Effect::Proxy { port, .. } => {
|
Effect::Proxy { port, .. } => {
|
||||||
let host = "0.0.0.0"; // Support for custom hosts added later
|
let host = "0.0.0.0"; // Support for custom hosts added later
|
||||||
let path = req
|
let path = req
|
||||||
.uri()
|
.uri()
|
||||||
.path_and_query()
|
.path_and_query()
|
||||||
.and_then(|x| {
|
.map(|x| x.as_str())
|
||||||
// Reject all requests where the path doesn't start with a `/`,
|
|
||||||
// and strip the first `/` off all paths so we can ensure that
|
|
||||||
// the path is actually separated from the host and port.
|
|
||||||
x.as_str().strip_prefix('/')
|
|
||||||
})
|
|
||||||
.unwrap_or("");
|
.unwrap_or("");
|
||||||
|
|
||||||
let target = format!("http://{host}:{port}/{path}");
|
let uri = Uri::builder()
|
||||||
|
.authority(format!("{host}:{port}"))
|
||||||
|
.scheme("http")
|
||||||
|
.path_and_query(path)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
println!("Proxying to {uri}");
|
||||||
|
|
||||||
let uri = target.parse().unwrap();
|
|
||||||
*req.uri_mut() = uri;
|
*req.uri_mut() = uri;
|
||||||
|
client.request(req).await?
|
||||||
println!("Proxying to {target}");
|
|
||||||
|
|
||||||
client.request(req).await
|
|
||||||
},
|
},
|
||||||
Effect::Redirect (uri) => Ok ({
|
Effect::Redirect (uri) => {
|
||||||
println!("Redirecting to {uri}");
|
println!("Redirecting to {uri}");
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.status(StatusCode::PERMANENT_REDIRECT)
|
.status(StatusCode::PERMANENT_REDIRECT)
|
||||||
.header("Location", uri)
|
.header("Location", uri)
|
||||||
.body(Body::empty())
|
.body(Body::empty())?
|
||||||
.unwrap()
|
},
|
||||||
}),
|
};
|
||||||
}
|
|
||||||
|
Ok (res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue