@@ -26,6 +26,7 @@ use tokio::fs;
2626use tokio:: time:: Duration ;
2727
2828use hyper_util:: client:: legacy:: Client as HyperClient ;
29+ use hyper_util:: client:: legacy:: connect:: HttpConnector ;
2930use hyper_util:: rt:: TokioExecutor ;
3031use http_body_util:: { BodyExt , Full } ;
3132use bytes:: Bytes ;
@@ -379,13 +380,19 @@ password = "admin"
379380 // Create traffic stats
380381 let traffic_stats = Arc :: new ( TrafficStats :: new ( ) ) ;
381382
383+ // Create HTTP connector with explicit configuration
384+ let mut connector = HttpConnector :: new ( ) ;
385+ connector. set_nodelay ( true ) ; // Disable Nagle's algorithm for lower latency
386+ connector. enforce_http ( false ) ; // Allow HTTPS URLs too
387+ connector. set_keepalive ( Some ( Duration :: from_secs ( 60 ) ) ) ; // TCP keepalive
388+
382389 // Create HTTP client for proxying with optimized settings
383390 let http_client = HyperClient :: builder ( TokioExecutor :: new ( ) )
384391 . pool_idle_timeout ( Duration :: from_secs ( 90 ) ) // Keep connections alive longer
385392 . pool_max_idle_per_host ( 100 ) // More idle connections per backend
386393 . retry_canceled_requests ( true ) // Retry if connection was closed
387394 . set_host ( false ) // We set Host header ourselves
388- . build_http ( ) ;
395+ . build ( connector ) ;
389396
390397 let vhost_count = vhosts. len ( ) ;
391398 let server_blocks = nginx_config. servers . len ( ) ;
@@ -964,6 +971,7 @@ async fn handle_proxy(
964971
965972 // Read the request body
966973 let method = req. method ( ) . clone ( ) ;
974+ let original_uri = req. uri ( ) . clone ( ) ;
967975 let ( _parts, body) = req. into_parts ( ) ;
968976 let body_bytes = match body. collect ( ) . await {
969977 Ok ( b) => b. to_bytes ( ) ,
@@ -1043,13 +1051,61 @@ async fn handle_proxy(
10431051 } ;
10441052
10451053 // Send the request
1046- debug ! ( "Proxying to {}" , uri) ;
1054+ info ! ( "Proxying {} {} -> {}" , method, original_uri, uri) ;
1055+
1056+ let backend_host = uri. host ( ) . unwrap_or ( "unknown" ) ;
1057+ let backend_port = uri. port_u16 ( ) . unwrap_or ( 80 ) ;
1058+ let backend_addr = format ! ( "{}:{}" , backend_host, backend_port) ;
10471059
10481060 let response = match state. http_client . request ( proxy_req) . await {
10491061 Ok ( r) => r,
10501062 Err ( e) => {
1051- error ! ( "Proxy request failed: {}" , e) ;
1052- return ( StatusCode :: BAD_GATEWAY , format ! ( "Upstream error: {}" , e) ) . into_response ( ) ;
1063+ // Provide detailed error information for troubleshooting
1064+ let error_details = format ! ( "{:?}" , e) ;
1065+ let error_lower = error_details. to_lowercase ( ) ;
1066+
1067+ let ( status, message) = if error_lower. contains ( "connecterror" ) || error_lower. contains ( "connect" ) {
1068+ // Connection refused, network unreachable, etc.
1069+ if error_lower. contains ( "refused" ) {
1070+ ( StatusCode :: BAD_GATEWAY , format ! (
1071+ "Connection refused to backend {} - check if the service is running on that port" ,
1072+ backend_addr
1073+ ) )
1074+ } else if error_lower. contains ( "unreachable" ) || error_lower. contains ( "no route" ) {
1075+ ( StatusCode :: BAD_GATEWAY , format ! (
1076+ "Network unreachable to backend {} - check network/firewall configuration" ,
1077+ backend_addr
1078+ ) )
1079+ } else {
1080+ ( StatusCode :: BAD_GATEWAY , format ! (
1081+ "Cannot connect to backend {} - verify the server is reachable and port is open" ,
1082+ backend_addr
1083+ ) )
1084+ }
1085+ } else if error_lower. contains ( "dns" ) || error_lower. contains ( "resolve" ) || error_lower. contains ( "lookup" ) {
1086+ ( StatusCode :: BAD_GATEWAY , format ! (
1087+ "DNS resolution failed for '{}' - check hostname or use IP address" ,
1088+ backend_host
1089+ ) )
1090+ } else if error_lower. contains ( "timeout" ) || error_lower. contains ( "timedout" ) {
1091+ ( StatusCode :: GATEWAY_TIMEOUT , format ! (
1092+ "Connection timeout to backend {} - server may be overloaded or unreachable" ,
1093+ backend_addr
1094+ ) )
1095+ } else if error_lower. contains ( "reset" ) {
1096+ ( StatusCode :: BAD_GATEWAY , format ! (
1097+ "Connection reset by backend {} - service may have crashed or rejected the connection" ,
1098+ backend_addr
1099+ ) )
1100+ } else {
1101+ ( StatusCode :: BAD_GATEWAY , format ! (
1102+ "Upstream error connecting to {}: {}" ,
1103+ backend_addr, e
1104+ ) )
1105+ } ;
1106+
1107+ error ! ( "Proxy request failed: {} -> {} : {} (raw: {})" , original_uri, backend_addr, message, error_details) ;
1108+ return ( status, message) . into_response ( ) ;
10531109 }
10541110 } ;
10551111
0 commit comments