More detailed error

This commit is contained in:
LittleSheep 2024-02-13 01:42:03 +08:00
parent 2478a05c89
commit e27023c130
5 changed files with 67 additions and 27 deletions

1
Cargo.lock generated
View File

@ -1277,6 +1277,7 @@ dependencies = [
"actix-web-httpauth",
"awc",
"config",
"derive_more",
"lazy_static",
"mime",
"percent-encoding",

View File

@ -31,3 +31,4 @@ toml = "0.8.8"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
wildmatch = "2.3.0"
derive_more = "0.99.17"

View File

@ -1,7 +1,9 @@
use actix_web::http::header::HeaderMap;
use actix_web::http::{Method, Uri};
use actix_web::http::header::{ContentType, HeaderMap};
use actix_web::http::{Method, StatusCode, Uri};
use regex::Regex;
use wildmatch::WildMatch;
use actix_web::{error, HttpResponse};
use derive_more::{Display};
use crate::warden::WardenInstance;
@ -16,6 +18,46 @@ pub mod metrics;
pub mod responder;
pub mod route;
#[derive(Debug, Display)]
pub enum ProxyError {
#[display(fmt = "Remote gateway issue")]
BadGateway,
#[display(fmt = "No configured able to process this request")]
NoGateway,
#[display(fmt = "Not found")]
NotFound,
#[display(fmt = "Only accepts method GET")]
MethodGetOnly,
#[display(fmt = "Invalid request path")]
InvalidRequestPath,
#[display(fmt = "Upstream does not support protocol you used")]
NotImplemented,
}
impl error::ResponseError for ProxyError {
fn status_code(&self) -> StatusCode {
match *self {
ProxyError::BadGateway => StatusCode::BAD_GATEWAY,
ProxyError::NoGateway => StatusCode::NOT_FOUND,
ProxyError::NotFound => StatusCode::NOT_FOUND,
ProxyError::MethodGetOnly => StatusCode::METHOD_NOT_ALLOWED,
ProxyError::InvalidRequestPath => StatusCode::BAD_REQUEST,
ProxyError::NotImplemented => StatusCode::NOT_IMPLEMENTED,
}
}
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code())
.insert_header(ContentType::html())
.body(self.to_string())
}
}
#[derive(Debug, Clone)]
pub struct RoadInstance {
pub regions: Vec<Region>,

View File

@ -7,12 +7,14 @@ use actix_proxy::IntoHttpResponse;
use actix_web::{HttpRequest, HttpResponse, web};
use actix_web::http::Method;
use awc::Client;
use tracing::log::warn;
use crate::proxies::ProxyError;
pub async fn respond_hypertext(
uri: String,
req: HttpRequest,
client: web::Data<Client>,
) -> Result<HttpResponse, HttpResponse> {
) -> Result<HttpResponse, ProxyError> {
let ip = req.peer_addr().unwrap().ip().to_string();
let proto = req.uri().scheme_str().unwrap();
let host = req.uri().host().unwrap();
@ -40,8 +42,8 @@ pub async fn respond_hypertext(
}
Err(error) => {
Err(HttpResponse::BadGateway()
.body(format!("Something went wrong... {:}", error)))
warn!("Proxy got a upstream issue... {:?}", error);
Err(ProxyError::BadGateway)
}
};
}
@ -59,10 +61,9 @@ pub struct StaticResponderConfig {
pub async fn respond_static(
cfg: StaticResponderConfig,
req: HttpRequest,
) -> Result<HttpResponse, HttpResponse> {
) -> Result<HttpResponse, ProxyError> {
if req.method() != Method::GET {
return Err(HttpResponse::MethodNotAllowed()
.body("This destination only support GET request."));
return Err(ProxyError::MethodGetOnly);
}
let path = req
@ -74,7 +75,7 @@ pub async fn respond_static(
let path = match percent_encoding::percent_decode_str(path).decode_utf8() {
Ok(val) => val,
Err(_) => {
return Err(HttpResponse::NotFound().body("Not found."));
return Err(ProxyError::NotFound);
}
};
@ -91,8 +92,7 @@ pub async fn respond_static(
}
if !file_path.starts_with(cfg.uri) {
return Err(HttpResponse::Forbidden()
.body("Unexpected path."));
return Err(ProxyError::InvalidRequestPath);
}
if !file_path.exists() {
@ -116,7 +116,7 @@ pub async fn respond_static(
}
}
return Err(HttpResponse::NotFound().body("Not found."));
return Err(ProxyError::NotFound);
}
return if file_path.is_file() {
@ -129,6 +129,6 @@ pub async fn respond_static(
}
}
Err(HttpResponse::NotFound().body("Not found."))
return Err(ProxyError::NotFound);
};
}

View File

@ -1,4 +1,4 @@
use actix_web::{HttpRequest, HttpResponse, web};
use actix_web::{HttpRequest, HttpResponse, ResponseError, web};
use actix_web::http::header;
use awc::Client;
use rand::seq::SliceRandom;
@ -10,14 +10,14 @@ use crate::{
},
ROAD,
};
use crate::proxies::ProxyError;
pub async fn handle(req: HttpRequest, client: web::Data<Client>) -> HttpResponse {
let readable_app = ROAD.lock().await;
let (region, location) = match readable_app.filter(req.uri(), req.method(), req.headers()) {
Some(val) => val,
None => {
return HttpResponse::NotFound()
.body("There are no region be able to respone this request.");
return ProxyError::NoGateway.error_response();
}
};
@ -30,29 +30,24 @@ pub async fn handle(req: HttpRequest, client: web::Data<Client>) -> HttpResponse
end: &Destination,
req: HttpRequest,
client: web::Data<Client>,
) -> Result<HttpResponse, HttpResponse> {
) -> Result<HttpResponse, ProxyError> {
// Handle normal web request
match end.get_type() {
DestinationType::Hypertext => {
let Ok(uri) = end.get_hypertext_uri() else {
return Err(HttpResponse::NotImplemented()
.body("This destination was not support web requests."));
return Err(ProxyError::NotImplemented);
};
responder::respond_hypertext(uri, req, client).await
}
DestinationType::StaticFiles => {
let Ok(cfg) = end.get_static_config() else {
return Err(HttpResponse::NotImplemented()
.body("This destination was not support static files."));
return Err(ProxyError::NotImplemented);
};
responder::respond_static(cfg, req).await
}
_ => {
return Err(HttpResponse::NotImplemented()
.body("Unsupported destination protocol."));
}
_ => Err(ProxyError::NotImplemented)
}
}
@ -78,13 +73,14 @@ pub async fn handle(req: HttpRequest, client: web::Data<Client>) -> HttpResponse
resp
}
Err(resp) => {
let message = resp.to_string();
tokio::spawn(async move {
let writable_app = &mut ROAD.lock().await;
writable_app
.metrics
.add_failure_request(ip, ua, reg, loc, end, "TODO".to_owned());
.add_failure_request(ip, ua, reg, loc, end, message);
});
resp
resp.error_response()
}
}
}