@@ -18,7 +18,7 @@ use rusty_ulid::Ulid;
1818use sozu_command:: {
1919 config:: MAX_LOOP_ITERATIONS ,
2020 logging:: EndpointRecord ,
21- proto:: command:: { Event , EventKind , ListenerType , RedirectScheme } ,
21+ proto:: command:: { Event , EventKind , ListenerType , RedirectPolicy , RedirectScheme } ,
2222} ;
2323// use time::{Duration, Instant};
2424
@@ -36,7 +36,7 @@ use crate::{
3636 SessionState ,
3737 } ,
3838 retry:: RetryPolicy ,
39- router:: { RouteDirection , RouteResult } ,
39+ router:: RouteResult ,
4040 server:: { push_event, CONN_RETRIES } ,
4141 socket:: { stats:: socket_rtt, SocketHandler , SocketResult , TransportProtocol } ,
4242 sozu_command:: { logging:: LogContext , ready:: Ready } ,
@@ -245,6 +245,7 @@ impl<Front: SocketHandler, L: ListenerHandler + L7ListenerHandler> Http<Front, L
245245 sticky_name,
246246 sticky_session : None ,
247247 sticky_session_found : None ,
248+ authentication_found : None ,
248249
249250 method : None ,
250251 authority : None ,
@@ -1295,91 +1296,92 @@ impl<Front: SocketHandler, L: ListenerHandler + L7ListenerHandler> Http<Front, L
12951296 . borrow ( )
12961297 . frontend_from_request ( host, path, method) ;
12971298
1298- let route = match route_result {
1299+ let RouteResult {
1300+ cluster_id,
1301+ redirect,
1302+ redirect_scheme,
1303+ redirect_template,
1304+ rewritten_host,
1305+ rewritten_path,
1306+ rewritten_port,
1307+ } = match route_result {
12991308 Ok ( route) => route,
13001309 Err ( frontend_error) => {
13011310 self . set_answer ( DefaultAnswer :: Answer404 { } ) ;
13021311 return Err ( RetrieveClusterError :: RetrieveFrontend ( frontend_error) ) ;
13031312 }
13041313 } ;
13051314
1306- match route {
1307- RouteResult :: Deny => {
1315+ if let Some ( cluster_id) = & cluster_id {
1316+ time ! (
1317+ "frontend_matching_time" ,
1318+ cluster_id,
1319+ start. elapsed( ) . as_millis( )
1320+ ) ;
1321+ }
1322+
1323+ let host = rewritten_host. as_deref ( ) . unwrap_or ( host) ;
1324+ let path = rewritten_path. as_deref ( ) . unwrap_or ( path) ;
1325+ let port = rewritten_port. map_or_else (
1326+ || {
1327+ port. map_or ( String :: new ( ) , |port| {
1328+ format ! ( ":{}" , unsafe { from_utf8_unchecked( port) } )
1329+ } )
1330+ } ,
1331+ |port| format ! ( ":{port}" ) ,
1332+ ) ;
1333+ let is_https = matches ! ( proxy. borrow( ) . kind( ) , ListenerType :: Https ) ;
1334+ let proto = match ( redirect_scheme, is_https) {
1335+ ( RedirectScheme :: UseHttp , _) | ( RedirectScheme :: UseSame , false ) => "http" ,
1336+ ( RedirectScheme :: UseHttps , _) | ( RedirectScheme :: UseSame , true ) => "https" ,
1337+ } ;
1338+
1339+ match ( cluster_id, redirect, redirect_template) {
1340+ ( _, RedirectPolicy :: Unauthorized , _) | ( None , RedirectPolicy :: Forward , None ) => {
13081341 self . set_answer ( DefaultAnswer :: Answer401 { } ) ;
1309- Err ( RetrieveClusterError :: UnauthorizedRoute )
1342+ return Err ( RetrieveClusterError :: UnauthorizedRoute ) ;
13101343 }
1311- RouteResult :: Flow {
1312- direction : flow,
1313- rewritten_host,
1314- rewritten_path,
1315- rewritten_port,
1316- } => {
1317- let is_https = matches ! ( proxy. borrow( ) . kind( ) , ListenerType :: Https ) ;
1318- if let RouteDirection :: Forward ( cluster_id) = & flow {
1319- time ! (
1320- "frontend_matching_time" ,
1321- cluster_id,
1322- start. elapsed( ) . as_millis( )
1323- ) ;
1324- let ( https_redirect, https_redirect_port, authentication) = proxy
1325- . borrow ( )
1326- . clusters ( )
1327- . get ( cluster_id)
1328- . map ( |cluster| {
1329- (
1330- cluster. https_redirect ,
1331- cluster. https_redirect_port ,
1332- None :: < ( ) > ,
1333- )
1334- } )
1335- . unwrap_or ( ( false , None , None ) ) ;
1336- if !is_https && https_redirect {
1337- let port = https_redirect_port
1338- . map_or ( String :: new ( ) , |port| format ! ( ":{}" , port as u16 ) ) ;
1339- self . set_answer ( DefaultAnswer :: Answer301 {
1340- location : format ! ( "https://{host}{port}{path}" ) ,
1341- } ) ;
1342- return Err ( RetrieveClusterError :: Redirected ) ;
1343- }
1344- if let Some ( authentication) = authentication {
1345- return Err ( RetrieveClusterError :: UnauthorizedRoute ) ;
1346- }
1344+ ( _, RedirectPolicy :: Permanent , _) => {
1345+ self . set_answer ( DefaultAnswer :: Answer301 {
1346+ location : format ! ( "{proto}://{host}{port}{path}" ) ,
1347+ } ) ;
1348+ Err ( RetrieveClusterError :: Redirected )
1349+ }
1350+ ( _, RedirectPolicy :: Temporary , _) => todo ! ( ) ,
1351+ ( cluster_id, RedirectPolicy :: Forward , Some ( name) ) => {
1352+ let location = format ! ( "{proto}://{host}{port}{path}" ) ;
1353+ // TODO: this feels wrong
1354+ self . context . cluster_id = cluster_id;
1355+ self . set_answer ( DefaultAnswer :: AnswerCustom { name, location } ) ;
1356+ Err ( RetrieveClusterError :: Redirected )
1357+ }
1358+ ( Some ( cluster_id) , RedirectPolicy :: Forward , None ) => {
1359+ let ( https_redirect, https_redirect_port, authentication) = proxy
1360+ . borrow ( )
1361+ . clusters ( )
1362+ . get ( & cluster_id)
1363+ . map ( |cluster| {
1364+ (
1365+ cluster. https_redirect ,
1366+ cluster. https_redirect_port ,
1367+ None :: < ( ) > ,
1368+ )
1369+ } )
1370+ . unwrap_or ( ( false , None , None ) ) ;
1371+ if !is_https && https_redirect {
1372+ let port = rewritten_port
1373+ . or_else ( || https_redirect_port. map ( |port| port as u16 ) )
1374+ . map_or ( String :: new ( ) , |port| format ! ( ":{port}" ) ) ;
1375+ self . set_answer ( DefaultAnswer :: Answer301 {
1376+ location : format ! ( "https://{host}{port}{path}" ) ,
1377+ } ) ;
1378+ return Err ( RetrieveClusterError :: Redirected ) ;
13471379 }
1348- let host = rewritten_host. as_deref ( ) . unwrap_or ( host) ;
1349- let path = rewritten_path. as_deref ( ) . unwrap_or ( path) ;
1350- let port = rewritten_port. map_or_else (
1351- || {
1352- port. map_or ( String :: new ( ) , |port| {
1353- format ! ( ":{}" , unsafe { from_utf8_unchecked( port) } )
1354- } )
1355- } ,
1356- |port| format ! ( ":{port}" ) ,
1357- ) ;
1358- match flow {
1359- RouteDirection :: Forward ( cluster_id) => Ok ( cluster_id) ,
1360- RouteDirection :: Permanent ( redirect_scheme) => {
1361- let proto = match ( redirect_scheme, is_https) {
1362- ( RedirectScheme :: UseHttp , _) | ( RedirectScheme :: UseSame , false ) => {
1363- "http"
1364- }
1365- ( RedirectScheme :: UseHttps , _) | ( RedirectScheme :: UseSame , true ) => {
1366- "https"
1367- }
1368- } ;
1369- self . set_answer ( DefaultAnswer :: Answer301 {
1370- location : format ! ( "{proto}://{host}{port}{path}" ) ,
1371- } ) ;
1372- Err ( RetrieveClusterError :: Redirected )
1373- }
1374- RouteDirection :: Temporary ( _) => todo ! ( ) ,
1375- RouteDirection :: Template ( cluster_id, name) => {
1376- let location = format ! ( "{host}{port}{path}" ) ;
1377- // TODO: this feels wrong
1378- self . context . cluster_id = cluster_id;
1379- self . set_answer ( DefaultAnswer :: AnswerCustom { name, location } ) ;
1380- Err ( RetrieveClusterError :: Redirected )
1381- }
1380+ if let Some ( authentication) = authentication {
1381+ self . set_answer ( DefaultAnswer :: Answer401 { } ) ;
1382+ return Err ( RetrieveClusterError :: UnauthorizedRoute ) ;
13821383 }
1384+ return Ok ( cluster_id) ;
13831385 }
13841386 }
13851387 }
0 commit comments