@@ -246,6 +246,7 @@ pub struct Url {
246246 path_start : u32 , // Before initial '/', if any
247247 query_start : Option < u32 > , // Before '?', unlike Position::QueryStart
248248 fragment_start : Option < u32 > , // Before '#', unlike Position::FragmentStart
249+ empty_first_segment : bool ,
249250}
250251
251252/// Full configuration for the URL parser.
@@ -2124,12 +2125,25 @@ impl Url {
21242125
21252126 /// opt_new_port: None means leave unchanged, Some(None) means remove any port number.
21262127 fn set_host_internal ( & mut self , host : Host < String > , opt_new_port : Option < Option < u16 > > ) {
2128+ // Check if the first segment is empty and there are at least two segments
2129+ // Update self.empty_first_segment flag since the hostname overwrites the blank segment
2130+ if self
2131+ . path_segments ( )
2132+ . map ( |mut segments| {
2133+ let empty_first_segment = segments. next ( ) . map_or ( false , |first| first. is_empty ( ) ) ;
2134+ empty_first_segment && segments. next ( ) . is_some ( )
2135+ } )
2136+ . unwrap_or ( false )
2137+ {
2138+ self . empty_first_segment = true ;
2139+ }
2140+
21272141 let old_suffix_pos = if opt_new_port. is_some ( ) {
21282142 self . path_start
21292143 } else {
21302144 self . host_end
21312145 } ;
2132- let suffix = self . slice ( old_suffix_pos..) . to_owned ( ) ;
2146+ let mut suffix = self . slice ( old_suffix_pos..) . to_owned ( ) ;
21332147 self . serialization . truncate ( self . host_start as usize ) ;
21342148 if !self . has_authority ( ) {
21352149 debug_assert ! ( self . slice( self . scheme_end..self . host_start) == ":" ) ;
@@ -2143,6 +2157,23 @@ impl Url {
21432157 self . host_end = to_u32 ( self . serialization . len ( ) ) . unwrap ( ) ;
21442158 self . host = host. into ( ) ;
21452159
2160+ // Adjust serialization to switch between host and empty segment
2161+ if self . empty_first_segment {
2162+ if suffix. starts_with ( "/.//" ) {
2163+ suffix = suffix[ "/." . len ( ) ..] . to_string ( ) ;
2164+ } else if self . host == HostInternal :: None && suffix. starts_with ( "/" ) {
2165+ if let Some ( index) = self . serialization . find ( ":" ) {
2166+ if self . serialization . len ( ) == index + "://" . len ( )
2167+ && self . serialization . as_bytes ( ) . get ( index + 1 ) == Some ( & b'/' )
2168+ && self . serialization . as_bytes ( ) . get ( index + 2 ) == Some ( & b'/' )
2169+ {
2170+ self . serialization
2171+ . replace_range ( index..index + "://" . len ( ) , ":/." ) ;
2172+ }
2173+ }
2174+ }
2175+ }
2176+
21462177 if let Some ( new_port) = opt_new_port {
21472178 self . port = new_port;
21482179 if let Some ( port) = new_port {
@@ -2157,6 +2188,10 @@ impl Url {
21572188 * index += new_suffix_pos;
21582189 } ;
21592190 adjust ( & mut self . path_start ) ;
2191+ // pathname should be "//p" not "p" given that the first segment was empty
2192+ if self . empty_first_segment {
2193+ self . path_start -= "//" . len ( ) as u32 ;
2194+ }
21602195 if let Some ( ref mut index) = self . query_start {
21612196 adjust ( index)
21622197 }
@@ -2605,6 +2640,7 @@ impl Url {
26052640 path_start : host_end,
26062641 query_start : None ,
26072642 fragment_start : None ,
2643+ empty_first_segment : false ,
26082644 } )
26092645 }
26102646
0 commit comments