@@ -78,13 +78,26 @@ private async Task<string> LoadStream(Stream stream, UiOptions options)
7878
7979 private static string ConstructRoutesPrefix ( UiOptions options )
8080 {
81- var safeHostPath = string . IsNullOrWhiteSpace ( options . ServerSubPath ) ? "" : options . ServerSubPath ;
82- var hostPathWithoutInitialSlash = safeHostPath . StartsWith ( "/" , StringComparison . OrdinalIgnoreCase ) ? safeHostPath [ 1 ..] : safeHostPath ;
83- var hostPathWithDivider = ! string . IsNullOrWhiteSpace ( hostPathWithoutInitialSlash ) &&
84- ! hostPathWithoutInitialSlash . EndsWith ( '/' )
85- ? $ "{ hostPathWithoutInitialSlash } /"
86- : hostPathWithoutInitialSlash ;
87-
88- return $ "{ hostPathWithDivider } { options . RoutePrefix } ";
81+ // If ServerSubPath is empty, just return the RoutePrefix
82+ if ( string . IsNullOrWhiteSpace ( options . ServerSubPath ) ) return options . RoutePrefix ;
83+
84+ // Create a span to avoid allocations when slicing
85+ ReadOnlySpan < char > path = options . ServerSubPath . AsSpan ( ) ;
86+ // Skip leading slash if present
87+ if ( path . Length > 0 && path [ 0 ] == '/' )
88+ {
89+ path = path [ 1 ..] ;
90+ }
91+
92+ // If the path is empty after removing the slash, just return the RoutePrefix
93+ if ( path . Length == 0 )
94+ {
95+ return options . RoutePrefix ;
96+ }
97+
98+ // Check if we need a trailing slash
99+ bool needsTrailingSlash = path . Length > 0 && path [ ^ 1 ] != '/' ;
100+ // Build the final string with minimal allocations
101+ return needsTrailingSlash ? string . Concat ( path . ToString ( ) , "/" , options . RoutePrefix ) : string . Concat ( path . ToString ( ) , options . RoutePrefix ) ;
89102 }
90103}
0 commit comments