@@ -246,6 +246,7 @@ pub struct Url {
246
246
path_start : u32 , // Before initial '/', if any
247
247
query_start : Option < u32 > , // Before '?', unlike Position::QueryStart
248
248
fragment_start : Option < u32 > , // Before '#', unlike Position::FragmentStart
249
+ empty_first_segment : bool ,
249
250
}
250
251
251
252
/// Full configuration for the URL parser.
@@ -2124,12 +2125,25 @@ impl Url {
2124
2125
2125
2126
/// opt_new_port: None means leave unchanged, Some(None) means remove any port number.
2126
2127
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
+
2127
2141
let old_suffix_pos = if opt_new_port. is_some ( ) {
2128
2142
self . path_start
2129
2143
} else {
2130
2144
self . host_end
2131
2145
} ;
2132
- let suffix = self . slice ( old_suffix_pos..) . to_owned ( ) ;
2146
+ let mut suffix = self . slice ( old_suffix_pos..) . to_owned ( ) ;
2133
2147
self . serialization . truncate ( self . host_start as usize ) ;
2134
2148
if !self . has_authority ( ) {
2135
2149
debug_assert ! ( self . slice( self . scheme_end..self . host_start) == ":" ) ;
@@ -2143,6 +2157,23 @@ impl Url {
2143
2157
self . host_end = to_u32 ( self . serialization . len ( ) ) . unwrap ( ) ;
2144
2158
self . host = host. into ( ) ;
2145
2159
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
+
2146
2177
if let Some ( new_port) = opt_new_port {
2147
2178
self . port = new_port;
2148
2179
if let Some ( port) = new_port {
@@ -2157,6 +2188,10 @@ impl Url {
2157
2188
* index += new_suffix_pos;
2158
2189
} ;
2159
2190
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
+ }
2160
2195
if let Some ( ref mut index) = self . query_start {
2161
2196
adjust ( index)
2162
2197
}
@@ -2605,6 +2640,7 @@ impl Url {
2605
2640
path_start : host_end,
2606
2641
query_start : None ,
2607
2642
fragment_start : None ,
2643
+ empty_first_segment : false ,
2608
2644
} )
2609
2645
}
2610
2646
0 commit comments