@@ -135,6 +135,8 @@ impl Http1Transaction for Server {
135135 let version;
136136 let len;
137137 let headers_len;
138+ let method;
139+ let path_range;
138140
139141 // Both headers_indices and headers are using uninitialized memory,
140142 // but we *never* read any of it until after httparse has assigned
@@ -162,10 +164,8 @@ impl Http1Transaction for Server {
162164 if uri. len ( ) > MAX_URI_LEN {
163165 return Err ( Parse :: UriTooLong ) ;
164166 }
165- subject = RequestLine (
166- Method :: from_bytes ( req. method . unwrap ( ) . as_bytes ( ) ) ?,
167- uri. parse ( ) ?,
168- ) ;
167+ method = Method :: from_bytes ( req. method . unwrap ( ) . as_bytes ( ) ) ?;
168+ path_range = Server :: record_path_range ( bytes, uri) ;
169169 version = if req. version . unwrap ( ) == 1 {
170170 keep_alive = true ;
171171 is_http_11 = true ;
@@ -198,6 +198,12 @@ impl Http1Transaction for Server {
198198 } ;
199199
200200 let slice = buf. split_to ( len) . freeze ( ) ;
201+ let uri = {
202+ let uri_bytes = slice. slice_ref ( & slice[ path_range] ) ;
203+ // TODO(lucab): switch to `Uri::from_shared()` once public.
204+ http:: Uri :: from_maybe_shared ( uri_bytes) ?
205+ } ;
206+ subject = RequestLine ( method, uri) ;
201207
202208 // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
203209 // 1. (irrelevant to Request)
@@ -945,6 +951,15 @@ impl Server {
945951
946952 Ok ( encoder. set_last ( is_last) )
947953 }
954+
955+ /// Helper for zero-copy parsing of request path URI.
956+ #[ inline]
957+ fn record_path_range ( bytes : & [ u8 ] , req_path : & str ) -> std:: ops:: Range < usize > {
958+ let bytes_ptr = bytes. as_ptr ( ) as usize ;
959+ let start = req_path. as_ptr ( ) as usize - bytes_ptr;
960+ let end = start + req_path. len ( ) ;
961+ std:: ops:: Range { start, end }
962+ }
948963}
949964
950965#[ cfg( feature = "server" ) ]
@@ -2936,8 +2951,12 @@ mod tests {
29362951 . unwrap ( )
29372952 . unwrap ( ) ;
29382953 :: test:: black_box ( & msg) ;
2954+
2955+ // Remove all references pointing into BytesMut.
29392956 msg. head . headers . clear ( ) ;
29402957 headers = Some ( msg. head . headers ) ;
2958+ std:: mem:: take ( & mut msg. head . subject ) ;
2959+
29412960 restart ( & mut raw, len) ;
29422961 } ) ;
29432962
0 commit comments