@@ -28,7 +28,7 @@ use axum::extract::{ConnectInfo, DefaultBodyLimit, Path, Query, State};
2828use axum:: http:: { header, HeaderMap , Method , Request , StatusCode , Uri } ;
2929use axum:: middleware:: { from_fn_with_state, Next } ;
3030use axum:: response:: { IntoResponse , Redirect , Response } ;
31- use axum:: routing:: { get, post} ;
31+ use axum:: routing:: { any , get, post} ;
3232use axum:: { Json , Router } ;
3333use bytes:: { Bytes , BytesMut } ;
3434use futures:: { SinkExt , StreamExt } ;
@@ -778,10 +778,9 @@ pub fn router(state: AppState) -> Router {
778778 . route ( "/api/inspector/response" , post ( inspector_response) )
779779 . route ( "/chrome-devtools-ui" , get ( chrome_devtools_ui_redirect) )
780780 . route ( "/chrome-devtools-ui/{*path}" , get ( chrome_devtools_ui_file) )
781- . route (
782- "/api/metro-frontend/{port}/{*path}" ,
783- get ( metro_frontend_asset) ,
784- )
781+ . route ( "/api/metro/{port}" , any ( metro_proxy_root) )
782+ . route ( "/api/metro/{port}/{*path}" , any ( metro_proxy_asset) )
783+ . route ( "/api/metro-frontend/{port}/{*path}" , any ( metro_proxy_asset) )
785784 . route ( "/webkit-inspector-ui" , get ( webkit_inspector_ui_redirect) )
786785 . route (
787786 "/webkit-inspector-ui/{*path}" ,
@@ -1084,7 +1083,11 @@ async fn chrome_devtools_targets(
10841083 } ;
10851084 let foreground_app_future = timeout (
10861085 FOREGROUND_APP_ROUTE_TIMEOUT ,
1087- foreground_app_for_simulator ( & state, & udid) ,
1086+ foreground_app_for_simulator_with_cache_ttl (
1087+ & state,
1088+ & udid,
1089+ INSPECTOR_FOREGROUND_APP_CACHE_TTL ,
1090+ ) ,
10881091 ) ;
10891092 let external_targets_future = timeout (
10901093 CHROME_DEVTOOLS_DISCOVERY_TIMEOUT ,
@@ -1230,24 +1233,77 @@ async fn webkit_inspector_ui_redirect() -> Redirect {
12301233 Redirect :: temporary ( "/webkit-inspector-ui/Main.html" )
12311234}
12321235
1233- async fn metro_frontend_asset ( Path ( ( port, path) ) : Path < ( u16 , String ) > , uri : Uri ) -> Response {
1234- let asset_path = format ! ( "/{path}" ) ;
1235- match devtools:: fetch_metro_frontend_asset ( port, & asset_path, uri. query ( ) ) . await {
1236+ async fn metro_proxy_root (
1237+ Path ( port) : Path < u16 > ,
1238+ method : Method ,
1239+ headers : HeaderMap ,
1240+ uri : Uri ,
1241+ body : Bytes ,
1242+ ) -> Response {
1243+ metro_proxy_response ( port, "/" , uri. query ( ) , method, headers, body) . await
1244+ }
1245+
1246+ async fn metro_proxy_asset (
1247+ Path ( ( port, path) ) : Path < ( u16 , String ) > ,
1248+ method : Method ,
1249+ headers : HeaderMap ,
1250+ uri : Uri ,
1251+ body : Bytes ,
1252+ ) -> Response {
1253+ metro_proxy_response (
1254+ port,
1255+ & format ! ( "/{path}" ) ,
1256+ uri. query ( ) ,
1257+ method,
1258+ headers,
1259+ body,
1260+ )
1261+ . await
1262+ }
1263+
1264+ async fn metro_proxy_response (
1265+ port : u16 ,
1266+ asset_path : & str ,
1267+ query : Option < & str > ,
1268+ method : Method ,
1269+ headers : HeaderMap ,
1270+ body : Bytes ,
1271+ ) -> Response {
1272+ let content_type = headers
1273+ . get ( header:: CONTENT_TYPE )
1274+ . and_then ( |value| value. to_str ( ) . ok ( ) ) ;
1275+ match devtools:: fetch_metro_resource (
1276+ port,
1277+ asset_path,
1278+ query,
1279+ method. as_str ( ) ,
1280+ Some ( body. as_ref ( ) ) ,
1281+ content_type,
1282+ )
1283+ . await
1284+ {
12361285 Ok ( asset) => {
12371286 let status = StatusCode :: from_u16 ( asset. status ) . unwrap_or ( StatusCode :: BAD_GATEWAY ) ;
1287+ let body = devtools:: rewrite_metro_proxy_asset (
1288+ port,
1289+ asset_path,
1290+ asset. content_type . as_deref ( ) ,
1291+ asset. body ,
1292+ ) ;
12381293 let mut builder = Response :: builder ( )
12391294 . status ( status)
12401295 . header ( header:: CACHE_CONTROL , "no-store" ) ;
12411296 if let Some ( content_type) = asset. content_type {
12421297 builder = builder. header ( header:: CONTENT_TYPE , content_type) ;
12431298 }
12441299 builder
1245- . body ( Body :: from ( asset . body ) )
1300+ . body ( Body :: from ( body) )
12461301 . unwrap_or_else ( |_| StatusCode :: INTERNAL_SERVER_ERROR . into_response ( ) )
12471302 }
12481303 Err ( error) => {
1249- tracing:: debug!( "Metro frontend asset proxy failed for {port}{asset_path}: {error}" ) ;
1250- AppError :: not_found ( "Metro DevTools frontend asset is not available." ) . into_response ( )
1304+ tracing:: debug!( "Metro proxy failed for {port}{asset_path}: {error}" ) ;
1305+ AppError :: not_found ( "Metro resource is not available through the proxy." )
1306+ . into_response ( )
12511307 }
12521308 }
12531309}
@@ -4642,7 +4698,11 @@ async fn foreground_app_for_simulator_with_cache_ttl(
46424698 }
46434699
46444700 let mut last_error: Option < String > = None ;
4645- match foreground_app_from_launchctl ( udid) . await {
4701+
4702+ // DevTools selection needs the app currently under the private display.
4703+ // launchctl can leave recently active UIKit services marked as active, so
4704+ // prefer the frontmost accessibility root when it is available.
4705+ match foreground_app_metadata ( state, udid) . await {
46464706 Ok ( Some ( foreground) ) => {
46474707 cache_foreground_app ( udid, & foreground) ;
46484708 return Ok ( Some ( foreground) ) ;
@@ -4651,7 +4711,7 @@ async fn foreground_app_for_simulator_with_cache_ttl(
46514711 Err ( error) => last_error = Some ( error) ,
46524712 }
46534713
4654- match foreground_app_metadata ( state , udid) . await {
4714+ match foreground_app_from_launchctl ( udid) . await {
46554715 Ok ( Some ( foreground) ) => {
46564716 cache_foreground_app ( udid, & foreground) ;
46574717 Ok ( Some ( foreground) )
0 commit comments