@@ -1781,20 +1781,26 @@ async fn proxy_webui_root_asset_fallback(
17811781 return StatusCode :: NOT_FOUND . into_response ( ) ;
17821782 } ;
17831783
1784- let mut path = format ! (
1785- "/api/v1/runtime/modules/{}/webui/files/{}" ,
1786- urlencoding:: encode( module_id. trim( ) ) ,
1787- relative_path
1788- ) ;
1789- if let Some ( query) = uri. query ( ) {
1790- path. push ( '?' ) ;
1791- path. push_str ( query) ;
1792- }
1784+ let candidates = fallback_webui_asset_candidates ( & relative_path) ;
1785+ for candidate in candidates {
1786+ let mut path = format ! (
1787+ "/api/v1/runtime/modules/{}/webui/files/{}" ,
1788+ urlencoding:: encode( module_id. trim( ) ) ,
1789+ candidate
1790+ ) ;
1791+ if let Some ( query) = uri. query ( ) {
1792+ path. push ( '?' ) ;
1793+ path. push_str ( query) ;
1794+ }
17931795
1794- match proxy_binary_response ( & state, Method :: GET , & path, HeaderMap :: new ( ) , None ) . await {
1795- Ok ( response) => response,
1796- Err ( error) => error. into_response ( ) ,
1796+ match proxy_binary_response ( & state, Method :: GET , & path, HeaderMap :: new ( ) , None ) . await {
1797+ Ok ( response) if response. status ( ) != StatusCode :: NOT_FOUND => return response,
1798+ Ok ( _) => continue ,
1799+ Err ( error) => return error. into_response ( ) ,
1800+ }
17971801 }
1802+
1803+ StatusCode :: NOT_FOUND . into_response ( )
17981804}
17991805
18001806async fn proxy_agent_json (
@@ -2522,7 +2528,19 @@ fn inject_html_base_href(html: &str, base_prefix: &str) -> String {
25222528 }
25232529
25242530 let base_tag = format ! ( r#"<base href="{base_prefix}">"# ) ;
2525- if let Some ( index) = html. to_ascii_lowercase ( ) . find ( "</head>" ) {
2531+ let lower = html. to_ascii_lowercase ( ) ;
2532+ if let Some ( head_index) = lower. find ( "<head" ) {
2533+ if let Some ( tag_end) = html[ head_index..] . find ( '>' ) {
2534+ let insert_at = head_index + tag_end + 1 ;
2535+ let mut output = String :: with_capacity ( html. len ( ) + base_tag. len ( ) ) ;
2536+ output. push_str ( & html[ ..insert_at] ) ;
2537+ output. push_str ( & base_tag) ;
2538+ output. push_str ( & html[ insert_at..] ) ;
2539+ return output;
2540+ }
2541+ }
2542+
2543+ if let Some ( index) = lower. find ( "</head>" ) {
25262544 let mut output = String :: with_capacity ( html. len ( ) + base_tag. len ( ) ) ;
25272545 output. push_str ( & html[ ..index] ) ;
25282546 output. push_str ( & base_tag) ;
@@ -2581,6 +2599,19 @@ fn fallback_webui_asset_target(
25812599 Some ( ( module_id, relative_path. to_string ( ) ) )
25822600}
25832601
2602+ fn fallback_webui_asset_candidates ( relative_path : & str ) -> Vec < String > {
2603+ let clean = relative_path. trim ( ) . trim_start_matches ( '/' ) . trim ( ) ;
2604+ if clean. is_empty ( ) {
2605+ return Vec :: new ( ) ;
2606+ }
2607+
2608+ let mut candidates = vec ! [ clean. to_string( ) ] ;
2609+ if !clean. contains ( '/' ) && !clean. starts_with ( "assets/" ) {
2610+ candidates. push ( format ! ( "assets/{clean}" ) ) ;
2611+ }
2612+ candidates
2613+ }
2614+
25842615fn forward_headers ( headers : & HeaderMap ) -> HeaderMap {
25852616 let mut forwarded = HeaderMap :: new ( ) ;
25862617 for ( name, value) in headers {
@@ -2768,6 +2799,7 @@ mod tests {
27682799 let html = String :: from_utf8 ( rewritten) . unwrap ( ) ;
27692800
27702801 assert ! ( html. contains( r#"<base href="/api/v1/runtime/modules/abi_bridge/webui/files/">"# ) ) ;
2802+ assert ! ( html. find( "<base " ) . unwrap( ) < html. find( "<script" ) . unwrap( ) ) ;
27712803 assert ! ( html
27722804 . contains( r#"src="/api/v1/runtime/modules/abi_bridge/webui/files/assets/index.js""# ) ) ;
27732805 assert ! ( html. contains( r#"href="assets/index.css""# ) ) ;
@@ -2810,4 +2842,19 @@ mod tests {
28102842
28112843 assert_eq ! ( resolved, None ) ;
28122844 }
2845+
2846+ #[ test]
2847+ fn expands_root_asset_fallback_to_assets_directory ( ) {
2848+ assert_eq ! (
2849+ fallback_webui_asset_candidates( "index-BphXklzb.js" ) ,
2850+ vec![
2851+ "index-BphXklzb.js" . to_string( ) ,
2852+ "assets/index-BphXklzb.js" . to_string( ) ,
2853+ ]
2854+ ) ;
2855+ assert_eq ! (
2856+ fallback_webui_asset_candidates( "assets/index-BphXklzb.js" ) ,
2857+ vec![ "assets/index-BphXklzb.js" . to_string( ) ]
2858+ ) ;
2859+ }
28132860}
0 commit comments