@@ -135,6 +135,8 @@ impl Http1Transaction for Server {
135
135
let version;
136
136
let len;
137
137
let headers_len;
138
+ let method;
139
+ let path_range;
138
140
139
141
// Both headers_indices and headers are using uninitialized memory,
140
142
// but we *never* read any of it until after httparse has assigned
@@ -162,10 +164,8 @@ impl Http1Transaction for Server {
162
164
if uri. len ( ) > MAX_URI_LEN {
163
165
return Err ( Parse :: UriTooLong ) ;
164
166
}
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) ;
169
169
version = if req. version . unwrap ( ) == 1 {
170
170
keep_alive = true ;
171
171
is_http_11 = true ;
@@ -198,6 +198,12 @@ impl Http1Transaction for Server {
198
198
} ;
199
199
200
200
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) ;
201
207
202
208
// According to https://tools.ietf.org/html/rfc7230#section-3.3.3
203
209
// 1. (irrelevant to Request)
@@ -945,6 +951,15 @@ impl Server {
945
951
946
952
Ok ( encoder. set_last ( is_last) )
947
953
}
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
+ }
948
963
}
949
964
950
965
#[ cfg( feature = "server" ) ]
@@ -2936,8 +2951,12 @@ mod tests {
2936
2951
. unwrap ( )
2937
2952
. unwrap ( ) ;
2938
2953
:: test:: black_box ( & msg) ;
2954
+
2955
+ // Remove all references pointing into BytesMut.
2939
2956
msg. head . headers . clear ( ) ;
2940
2957
headers = Some ( msg. head . headers ) ;
2958
+ std:: mem:: take ( & mut msg. head . subject ) ;
2959
+
2941
2960
restart ( & mut raw, len) ;
2942
2961
} ) ;
2943
2962
0 commit comments