@@ -27,7 +27,7 @@ use axum::extract::{ConnectInfo, DefaultBodyLimit, Path, Query, State};
2727use axum:: http:: { header, HeaderMap , Method , Request , StatusCode , Uri } ;
2828use axum:: middleware:: { from_fn_with_state, Next } ;
2929use axum:: response:: { IntoResponse , Redirect , Response } ;
30- use axum:: routing:: { get, post} ;
30+ use axum:: routing:: { any , get, post} ;
3131use axum:: { Json , Router } ;
3232use bytes:: { Bytes , BytesMut } ;
3333use futures:: { SinkExt , StreamExt } ;
@@ -777,10 +777,9 @@ pub fn router(state: AppState) -> Router {
777777 . route ( "/api/inspector/response" , post ( inspector_response) )
778778 . route ( "/chrome-devtools-ui" , get ( chrome_devtools_ui_redirect) )
779779 . route ( "/chrome-devtools-ui/{*path}" , get ( chrome_devtools_ui_file) )
780- . route (
781- "/api/metro-frontend/{port}/{*path}" ,
782- get ( metro_frontend_asset) ,
783- )
780+ . route ( "/api/metro/{port}" , any ( metro_proxy_root) )
781+ . route ( "/api/metro/{port}/{*path}" , any ( metro_proxy_asset) )
782+ . route ( "/api/metro-frontend/{port}/{*path}" , any ( metro_proxy_asset) )
784783 . route ( "/webkit-inspector-ui" , get ( webkit_inspector_ui_redirect) )
785784 . route (
786785 "/webkit-inspector-ui/{*path}" ,
@@ -1074,7 +1073,11 @@ async fn chrome_devtools_targets(
10741073 } ;
10751074 let foreground_app_future = timeout (
10761075 FOREGROUND_APP_ROUTE_TIMEOUT ,
1077- foreground_app_for_simulator ( & state, & udid) ,
1076+ foreground_app_for_simulator_with_cache_ttl (
1077+ & state,
1078+ & udid,
1079+ INSPECTOR_FOREGROUND_APP_CACHE_TTL ,
1080+ ) ,
10781081 ) ;
10791082 let external_targets_future = timeout (
10801083 CHROME_DEVTOOLS_DISCOVERY_TIMEOUT ,
@@ -1220,24 +1223,77 @@ async fn webkit_inspector_ui_redirect() -> Redirect {
12201223 Redirect :: temporary ( "/webkit-inspector-ui/Main.html" )
12211224}
12221225
1223- async fn metro_frontend_asset ( Path ( ( port, path) ) : Path < ( u16 , String ) > , uri : Uri ) -> Response {
1224- let asset_path = format ! ( "/{path}" ) ;
1225- match devtools:: fetch_metro_frontend_asset ( port, & asset_path, uri. query ( ) ) . await {
1226+ async fn metro_proxy_root (
1227+ Path ( port) : Path < u16 > ,
1228+ method : Method ,
1229+ headers : HeaderMap ,
1230+ uri : Uri ,
1231+ body : Bytes ,
1232+ ) -> Response {
1233+ metro_proxy_response ( port, "/" , uri. query ( ) , method, headers, body) . await
1234+ }
1235+
1236+ async fn metro_proxy_asset (
1237+ Path ( ( port, path) ) : Path < ( u16 , String ) > ,
1238+ method : Method ,
1239+ headers : HeaderMap ,
1240+ uri : Uri ,
1241+ body : Bytes ,
1242+ ) -> Response {
1243+ metro_proxy_response (
1244+ port,
1245+ & format ! ( "/{path}" ) ,
1246+ uri. query ( ) ,
1247+ method,
1248+ headers,
1249+ body,
1250+ )
1251+ . await
1252+ }
1253+
1254+ async fn metro_proxy_response (
1255+ port : u16 ,
1256+ asset_path : & str ,
1257+ query : Option < & str > ,
1258+ method : Method ,
1259+ headers : HeaderMap ,
1260+ body : Bytes ,
1261+ ) -> Response {
1262+ let content_type = headers
1263+ . get ( header:: CONTENT_TYPE )
1264+ . and_then ( |value| value. to_str ( ) . ok ( ) ) ;
1265+ match devtools:: fetch_metro_resource (
1266+ port,
1267+ asset_path,
1268+ query,
1269+ method. as_str ( ) ,
1270+ Some ( body. as_ref ( ) ) ,
1271+ content_type,
1272+ )
1273+ . await
1274+ {
12261275 Ok ( asset) => {
12271276 let status = StatusCode :: from_u16 ( asset. status ) . unwrap_or ( StatusCode :: BAD_GATEWAY ) ;
1277+ let body = devtools:: rewrite_metro_proxy_asset (
1278+ port,
1279+ asset_path,
1280+ asset. content_type . as_deref ( ) ,
1281+ asset. body ,
1282+ ) ;
12281283 let mut builder = Response :: builder ( )
12291284 . status ( status)
12301285 . header ( header:: CACHE_CONTROL , "no-store" ) ;
12311286 if let Some ( content_type) = asset. content_type {
12321287 builder = builder. header ( header:: CONTENT_TYPE , content_type) ;
12331288 }
12341289 builder
1235- . body ( Body :: from ( asset . body ) )
1290+ . body ( Body :: from ( body) )
12361291 . unwrap_or_else ( |_| StatusCode :: INTERNAL_SERVER_ERROR . into_response ( ) )
12371292 }
12381293 Err ( error) => {
1239- tracing:: debug!( "Metro frontend asset proxy failed for {port}{asset_path}: {error}" ) ;
1240- AppError :: not_found ( "Metro DevTools frontend asset is not available." ) . into_response ( )
1294+ tracing:: debug!( "Metro proxy failed for {port}{asset_path}: {error}" ) ;
1295+ AppError :: not_found ( "Metro resource is not available through the proxy." )
1296+ . into_response ( )
12411297 }
12421298 }
12431299}
@@ -4563,7 +4619,11 @@ async fn foreground_app_for_simulator_with_cache_ttl(
45634619 }
45644620
45654621 let mut last_error: Option < String > = None ;
4566- match foreground_app_from_launchctl ( udid) . await {
4622+
4623+ // DevTools selection needs the app currently under the private display.
4624+ // launchctl can leave recently active UIKit services marked as active, so
4625+ // prefer the frontmost accessibility root when it is available.
4626+ match foreground_app_metadata ( state, udid) . await {
45674627 Ok ( Some ( foreground) ) => {
45684628 cache_foreground_app ( udid, & foreground) ;
45694629 return Ok ( Some ( foreground) ) ;
@@ -4572,7 +4632,7 @@ async fn foreground_app_for_simulator_with_cache_ttl(
45724632 Err ( error) => last_error = Some ( error) ,
45734633 }
45744634
4575- match foreground_app_metadata ( state , udid) . await {
4635+ match foreground_app_from_launchctl ( udid) . await {
45764636 Ok ( Some ( foreground) ) => {
45774637 cache_foreground_app ( udid, & foreground) ;
45784638 Ok ( Some ( foreground) )
0 commit comments