✨ More detailed error
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -1277,6 +1277,7 @@ dependencies = [ | ||||
|  "actix-web-httpauth", | ||||
|  "awc", | ||||
|  "config", | ||||
|  "derive_more", | ||||
|  "lazy_static", | ||||
|  "mime", | ||||
|  "percent-encoding", | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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>, | ||||
|   | ||||
| @@ -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); | ||||
|     }; | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user