@@ -8,10 +8,12 @@ use std::{
88 io:: ErrorKind ,
99 net:: { Shutdown , SocketAddr } ,
1010 rc:: { Rc , Weak } ,
11+ str:: from_utf8_unchecked,
1112 time:: { Duration , Instant } ,
1213} ;
1314
1415use mio:: { net:: TcpStream , Interest , Token } ;
16+ use parser:: hostname_and_port;
1517use rusty_ulid:: Ulid ;
1618use sozu_command:: {
1719 config:: MAX_LOOP_ITERATIONS ,
@@ -40,8 +42,9 @@ use crate::{
4042 sozu_command:: { logging:: LogContext , ready:: Ready } ,
4143 timer:: TimeoutContainer ,
4244 AcceptError , BackendConnectAction , BackendConnectionError , BackendConnectionStatus ,
43- L7ListenerHandler , L7Proxy , ListenerHandler , Protocol , ProxySession , Readiness ,
44- RetrieveClusterError , SessionIsToBeClosed , SessionMetrics , SessionResult , StateResult ,
45+ FrontendFromRequestError , L7ListenerHandler , L7Proxy , ListenerHandler , Protocol , ProxySession ,
46+ Readiness , RetrieveClusterError , SessionIsToBeClosed , SessionMetrics , SessionResult ,
47+ StateResult ,
4548} ;
4649
4750/// This macro is defined uniquely in this module to help the tracking of kawa h1
@@ -1257,7 +1260,7 @@ impl<Front: SocketHandler, L: ListenerHandler + L7ListenerHandler> Http<Front, L
12571260 Err ( cluster_error) => {
12581261 self . set_answer ( DefaultAnswer :: Answer400 {
12591262 message : "Could not extract the route after connection started, this should not happen." . into ( ) ,
1260- phase : self . request_stream . parsing_phase . marker ( ) ,
1263+ phase : kawa :: ParsingPhaseMarker :: StatusLine ,
12611264 successfully_parsed : "null" . into ( ) ,
12621265 partially_parsed : "null" . into ( ) ,
12631266 invalid : "null" . into ( ) ,
@@ -1266,6 +1269,38 @@ impl<Front: SocketHandler, L: ListenerHandler + L7ListenerHandler> Http<Front, L
12661269 }
12671270 } ;
12681271
1272+ let ( host, port) = match hostname_and_port ( host. as_bytes ( ) ) {
1273+ Ok ( ( b"" , ( hostname, port) ) ) => ( unsafe { from_utf8_unchecked ( hostname) } , port) ,
1274+ Ok ( _) => {
1275+ let host = host. to_owned ( ) ;
1276+ self . set_answer ( DefaultAnswer :: Answer400 {
1277+ message : "Invalid characters after hostname, this should not happen." . into ( ) ,
1278+ phase : kawa:: ParsingPhaseMarker :: StatusLine ,
1279+ successfully_parsed : "null" . into ( ) ,
1280+ partially_parsed : "null" . into ( ) ,
1281+ invalid : "null" . into ( ) ,
1282+ } ) ;
1283+ return Err ( RetrieveClusterError :: RetrieveFrontend (
1284+ FrontendFromRequestError :: InvalidCharsAfterHost ( host) ,
1285+ ) ) ;
1286+ }
1287+ Err ( parse_error) => {
1288+ let host = host. to_owned ( ) ;
1289+ let error = parse_error. to_string ( ) ;
1290+ self . set_answer ( DefaultAnswer :: Answer400 {
1291+ message : "Could not parse port from hostname, this should not happen." . into ( ) ,
1292+ phase : kawa:: ParsingPhaseMarker :: StatusLine ,
1293+ successfully_parsed : "null" . into ( ) ,
1294+ partially_parsed : "null" . into ( ) ,
1295+ invalid : "null" . into ( ) ,
1296+ } ) ;
1297+ return Err ( RetrieveClusterError :: RetrieveFrontend (
1298+ FrontendFromRequestError :: HostParse { host, error } ,
1299+ ) ) ;
1300+ }
1301+ } ;
1302+
1303+ let start = Instant :: now ( ) ;
12691304 let route_result = self
12701305 . listener
12711306 . borrow ( )
@@ -1288,25 +1323,43 @@ impl<Front: SocketHandler, L: ListenerHandler + L7ListenerHandler> Http<Front, L
12881323 direction : flow,
12891324 rewritten_host,
12901325 rewritten_path,
1326+ rewritten_port,
12911327 } => {
12921328 let is_https = matches ! ( proxy. borrow( ) . kind( ) , ListenerType :: Https ) ;
12931329 if let RouteDirection :: Forward ( cluster_id) = & flow {
1294- if !is_https
1295- && proxy
1296- . borrow ( )
1297- . clusters ( )
1298- . get ( cluster_id)
1299- . map ( |cluster| cluster. https_redirect )
1300- . unwrap_or ( false )
1301- {
1330+ time ! (
1331+ "frontend_matching_time" ,
1332+ cluster_id,
1333+ start. elapsed( ) . as_millis( )
1334+ ) ;
1335+ let ( https_redirect, https_redirect_port, authentication) = proxy
1336+ . borrow ( )
1337+ . clusters ( )
1338+ . get ( cluster_id)
1339+ . map ( |cluster| ( cluster. https_redirect , Some ( 8443 ) , None :: < ( ) > ) )
1340+ . unwrap_or ( ( false , None , None ) ) ;
1341+ if !is_https && https_redirect {
1342+ let port =
1343+ https_redirect_port. map_or ( String :: new ( ) , |port| format ! ( ":{port}" ) ) ;
13021344 self . set_answer ( DefaultAnswer :: Answer301 {
1303- location : format ! ( "https://{host}{path}" ) ,
1345+ location : format ! ( "https://{host}{port}{ path}" ) ,
13041346 } ) ;
13051347 return Err ( RetrieveClusterError :: Redirected ) ;
13061348 }
1349+ if let Some ( authentication) = authentication {
1350+ return Err ( RetrieveClusterError :: UnauthorizedRoute ) ;
1351+ }
13071352 }
13081353 let host = rewritten_host. as_deref ( ) . unwrap_or ( host) ;
13091354 let path = rewritten_path. as_deref ( ) . unwrap_or ( path) ;
1355+ let port = rewritten_port. map_or_else (
1356+ || {
1357+ port. map_or ( String :: new ( ) , |port| {
1358+ format ! ( ":{}" , unsafe { from_utf8_unchecked( port) } )
1359+ } )
1360+ } ,
1361+ |port| format ! ( ":{port}" ) ,
1362+ ) ;
13101363 match flow {
13111364 RouteDirection :: Forward ( cluster_id) => Ok ( cluster_id) ,
13121365 RouteDirection :: Permanent ( redirect_scheme) => {
@@ -1319,7 +1372,7 @@ impl<Front: SocketHandler, L: ListenerHandler + L7ListenerHandler> Http<Front, L
13191372 }
13201373 } ;
13211374 self . set_answer ( DefaultAnswer :: Answer301 {
1322- location : format ! ( "{proto}://{host}{path}" ) ,
1375+ location : format ! ( "{proto}://{host}{port}{ path}" ) ,
13231376 } ) ;
13241377 Err ( RetrieveClusterError :: Redirected )
13251378 }
0 commit comments