22// SPDX-License-Identifier: Apache-2.0
33
44use std:: collections:: VecDeque ;
5+ use std:: fs:: File ;
56use std:: io:: { Read , Write } ;
67
78use crate :: common:: ascii:: { CR , CRLF_LEN , LF } ;
@@ -50,6 +51,9 @@ pub struct HttpConnection<T> {
5051 /// A buffer containing the bytes of a response that is currently
5152 /// being sent.
5253 response_buffer : Option < Vec < u8 > > ,
54+ /// The latest file that has been received and which must be associated
55+ /// with the pending request.
56+ file : Option < File > ,
5357}
5458
5559impl < T : Read + Write + ScmSocket > HttpConnection < T > {
@@ -66,6 +70,7 @@ impl<T: Read + Write + ScmSocket> HttpConnection<T> {
6670 parsed_requests : VecDeque :: new ( ) ,
6771 response_queue : VecDeque :: new ( ) ,
6872 response_buffer : None ,
73+ file : None ,
6974 }
7075 }
7176
@@ -107,8 +112,9 @@ impl<T: Read + Write + ScmSocket> HttpConnection<T> {
107112 // the `parsed_requests` queue.
108113 self . state = ConnectionState :: WaitingForRequestLine ;
109114 self . body_bytes_to_be_read = 0 ;
110- self . parsed_requests
111- . push_back ( self . pending_request . take ( ) . unwrap ( ) ) ;
115+ let mut pending_request = self . pending_request . take ( ) . unwrap ( ) ;
116+ pending_request. file = self . file . take ( ) ;
117+ self . parsed_requests . push_back ( pending_request) ;
112118 }
113119 } ;
114120 }
@@ -127,11 +133,16 @@ impl<T: Read + Write + ScmSocket> HttpConnection<T> {
127133 }
128134 // Append new bytes to what we already have in the buffer.
129135 // The slice access is safe, the index is checked above.
130- let ( bytes_read, _ ) = self
136+ let ( bytes_read, file ) = self
131137 . stream
132138 . recv_with_fd ( & mut self . buffer [ self . read_cursor ..] )
133139 . map_err ( ConnectionError :: StreamReadError ) ?;
134140
141+ // Update the internal file that must be associated with the request.
142+ if file. is_some ( ) {
143+ self . file = file;
144+ }
145+
135146 // If the read returned 0 then the client has closed the connection.
136147 if bytes_read == 0 {
137148 return Err ( ConnectionError :: ConnectionClosed ) ;
@@ -176,6 +187,7 @@ impl<T: Read + Write + ScmSocket> HttpConnection<T> {
176187 . map_err ( ConnectionError :: ParseError ) ?,
177188 headers : Headers :: default ( ) ,
178189 body : None ,
190+ file : None ,
179191 } ) ;
180192 self . state = ConnectionState :: WaitingForHeaders ;
181193 Ok ( true )
@@ -517,6 +529,7 @@ mod tests {
517529 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
518530 headers : Headers :: new ( 26 , true , true ) ,
519531 body : Some ( Body :: new ( b"this is not\n \r \n a json \n body" . to_vec ( ) ) ) ,
532+ file : None ,
520533 } ;
521534
522535 assert_eq ! ( request, expected_request) ;
@@ -553,6 +566,7 @@ mod tests {
553566 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
554567 headers : Headers :: new ( 26 , true , true ) ,
555568 body : Some ( Body :: new ( b"this is not\n \r \n a json \n body" . to_vec ( ) ) ) ,
569+ file : None ,
556570 } ;
557571 assert_eq ! ( request, expected_request) ;
558572 }
@@ -586,6 +600,7 @@ mod tests {
586600 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
587601 headers : Headers :: new ( 26 , true , true ) ,
588602 body : Some ( Body :: new ( b"this is not\n \r \n a json \n body" . to_vec ( ) ) ) ,
603+ file : None ,
589604 } ;
590605 assert_eq ! ( request, expected_request) ;
591606 }
@@ -650,6 +665,7 @@ mod tests {
650665 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
651666 headers : Headers :: new ( 1400 , true , true ) ,
652667 body : Some ( Body :: new ( request_body) ) ,
668+ file : None ,
653669 } ;
654670
655671 assert_eq ! ( request, expected_request) ;
@@ -720,6 +736,7 @@ mod tests {
720736 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
721737 headers : Headers :: new ( 0 , true , true ) ,
722738 body : None ,
739+ file : None ,
723740 } ;
724741 assert_eq ! ( request, expected_request) ;
725742 }
@@ -741,6 +758,7 @@ mod tests {
741758 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
742759 headers : Headers :: new ( 0 , false , false ) ,
743760 body : None ,
761+ file : None ,
744762 } ;
745763 assert_eq ! ( request, expected_request) ;
746764 }
@@ -769,6 +787,7 @@ mod tests {
769787 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
770788 headers : Headers :: new ( 0 , false , false ) ,
771789 body : None ,
790+ file : None ,
772791 } ;
773792 assert_eq ! ( request, expected_request) ;
774793
@@ -787,6 +806,7 @@ mod tests {
787806 ) ,
788807 headers : Headers :: new ( 0 , false , false ) ,
789808 body : None ,
809+ file : None ,
790810 } ;
791811 assert_eq ! ( request, expected_request) ;
792812 }
@@ -814,6 +834,7 @@ mod tests {
814834 request_line : RequestLine :: new ( Method :: Patch , "http://localhost/home" , Version :: Http11 ) ,
815835 headers : Headers :: new ( 26 , false , true ) ,
816836 body : Some ( Body :: new ( b"this is not\n \r \n a json \n body" . to_vec ( ) ) ) ,
837+ file : None ,
817838 } ;
818839
819840 conn. try_read ( ) . unwrap ( ) ;
@@ -824,6 +845,7 @@ mod tests {
824845 request_line : RequestLine :: new ( Method :: Put , "http://farhost/away" , Version :: Http11 ) ,
825846 headers : Headers :: new ( 23 , false , false ) ,
826847 body : Some ( Body :: new ( b"this is another request" . to_vec ( ) ) ) ,
848+ file : None ,
827849 } ;
828850 assert_eq ! ( request_first, expected_request_first) ;
829851 assert_eq ! ( request_second, expected_request_second) ;
@@ -1036,6 +1058,7 @@ mod tests {
10361058 request_line : RequestLine :: new ( Method :: Get , "http://foo/bar" , Version :: Http11 ) ,
10371059 headers : Headers :: new ( 0 , true , true ) ,
10381060 body : None ,
1061+ file : None ,
10391062 } ) ;
10401063 assert_eq ! (
10411064 conn. parse_headers( & mut 0 , BUFFER_SIZE ) . unwrap_err( ) ,
@@ -1093,6 +1116,7 @@ mod tests {
10931116 request_line : RequestLine :: new ( Method :: Get , "http://foo/bar" , Version :: Http11 ) ,
10941117 headers : Headers :: new ( 0 , true , true ) ,
10951118 body : None ,
1119+ file : None ,
10961120 } ) ;
10971121 conn. body_vec = vec ! [ 0xde , 0xad , 0xbe , 0xef ] ;
10981122 assert_eq ! (
0 commit comments