@@ -88,6 +88,9 @@ where I: AsyncRead + AsyncWrite,
8888 trace ! ( "poll when on keep-alive" ) ;
8989 if !T :: should_read_first ( ) {
9090 self . try_empty_read ( ) ?;
91+ if self . is_read_closed ( ) {
92+ return Ok ( Async :: Ready ( None ) ) ;
93+ }
9194 }
9295 self . maybe_park_read ( ) ;
9396 return Ok ( Async :: NotReady ) ;
@@ -134,6 +137,11 @@ where I: AsyncRead + AsyncWrite,
134137 }
135138 }
136139
140+ fn should_error_on_eof ( & self ) -> bool {
141+ // If we're idle, it's probably just the connection closing gracefully.
142+ T :: should_error_on_parse_eof ( ) && !self . state . is_idle ( )
143+ }
144+
137145 pub fn read_head ( & mut self ) -> Poll < Option < ( super :: MessageHead < T :: Incoming > , bool ) > , :: Error > {
138146 debug_assert ! ( self . can_read_head( ) ) ;
139147 trace ! ( "Conn::read_head" ) ;
@@ -145,7 +153,7 @@ where I: AsyncRead + AsyncWrite,
145153 // If we are currently waiting on a message, then an empty
146154 // message should be reported as an error. If not, it is just
147155 // the connection closing gracefully.
148- let must_error = ! self . state . is_idle ( ) && T :: should_error_on_parse_eof ( ) ;
156+ let must_error = self . should_error_on_eof ( ) ;
149157 self . state . close_read ( ) ;
150158 self . io . consume_leading_lines ( ) ;
151159 let was_mid_parse = !self . io . read_buf ( ) . is_empty ( ) ;
@@ -185,6 +193,9 @@ where I: AsyncRead + AsyncWrite,
185193 ( true , Reading :: Body ( decoder) )
186194 } ;
187195 self . state . reading = reading;
196+ if !body {
197+ self . try_keep_alive ( ) ;
198+ }
188199 Ok ( Async :: Ready ( Some ( ( head, body) ) ) )
189200 } ,
190201 _ => {
@@ -219,6 +230,7 @@ where I: AsyncRead + AsyncWrite,
219230 } ;
220231
221232 self . state . reading = reading;
233+ self . try_keep_alive ( ) ;
222234 ret
223235 }
224236
@@ -251,11 +263,12 @@ where I: AsyncRead + AsyncWrite,
251263 } else {
252264 match self . io . read_from_io ( ) {
253265 Ok ( Async :: Ready ( 0 ) ) => {
254- trace ! ( "try_empty_read; found EOF on connection" ) ;
266+ trace ! ( "try_empty_read; found EOF on connection: {:?}" , self . state) ;
267+ let must_error = self . should_error_on_eof ( ) ;
268+ // order is important: must_error needs state BEFORE close_read
255269 self . state . close_read ( ) ;
256- let must_error = !self . state . is_idle ( ) && T :: should_error_on_parse_eof ( ) ;
257270 if must_error {
258- Err ( io:: ErrorKind :: UnexpectedEof . into ( ) )
271+ Err ( io:: Error :: new ( io :: ErrorKind :: UnexpectedEof , "unexpected EOF waiting for response" ) )
259272 } else {
260273 Ok ( ( ) )
261274 }
@@ -860,7 +873,7 @@ mod tests {
860873 use super :: super :: h1:: Encoder ;
861874 use mock:: AsyncIo ;
862875
863- use super :: { Conn , Reading , Writing } ;
876+ use super :: { Conn , Decoder , Reading , Writing } ;
864877 use :: uri:: Uri ;
865878
866879 use std:: str:: FromStr ;
@@ -960,6 +973,55 @@ mod tests {
960973 } ) . wait ( ) ;
961974 }
962975
976+ #[ test]
977+ fn test_conn_body_finish_read_eof ( ) {
978+ let _: Result < ( ) , ( ) > = future:: lazy ( || {
979+ let io = AsyncIo :: new_eof ( ) ;
980+ let mut conn = Conn :: < _ , proto:: Chunk , ClientTransaction > :: new ( io, Default :: default ( ) ) ;
981+ conn. state . busy ( ) ;
982+ conn. state . writing = Writing :: KeepAlive ;
983+ conn. state . reading = Reading :: Body ( Decoder :: length ( 0 ) ) ;
984+
985+ match conn. poll ( ) {
986+ Ok ( Async :: Ready ( Some ( Frame :: Body { chunk : None } ) ) ) => ( ) ,
987+ other => panic ! ( "unexpected frame: {:?}" , other)
988+ }
989+
990+ // conn eofs, but tokio-proto will call poll() again, before calling flush()
991+ // the conn eof in this case is perfectly fine
992+
993+ match conn. poll ( ) {
994+ Ok ( Async :: Ready ( None ) ) => ( ) ,
995+ other => panic ! ( "unexpected frame: {:?}" , other)
996+ }
997+ Ok ( ( ) )
998+ } ) . wait ( ) ;
999+ }
1000+
1001+ #[ test]
1002+ fn test_conn_message_empty_body_read_eof ( ) {
1003+ let _: Result < ( ) , ( ) > = future:: lazy ( || {
1004+ let io = AsyncIo :: new_buf ( b"HTTP/1.1 200 OK\r \n Content-Length: 0\r \n \r \n " . to_vec ( ) , 1024 ) ;
1005+ let mut conn = Conn :: < _ , proto:: Chunk , ClientTransaction > :: new ( io, Default :: default ( ) ) ;
1006+ conn. state . busy ( ) ;
1007+ conn. state . writing = Writing :: KeepAlive ;
1008+
1009+ match conn. poll ( ) {
1010+ Ok ( Async :: Ready ( Some ( Frame :: Message { body : false , .. } ) ) ) => ( ) ,
1011+ other => panic ! ( "unexpected frame: {:?}" , other)
1012+ }
1013+
1014+ // conn eofs, but tokio-proto will call poll() again, before calling flush()
1015+ // the conn eof in this case is perfectly fine
1016+
1017+ match conn. poll ( ) {
1018+ Ok ( Async :: Ready ( None ) ) => ( ) ,
1019+ other => panic ! ( "unexpected frame: {:?}" , other)
1020+ }
1021+ Ok ( ( ) )
1022+ } ) . wait ( ) ;
1023+ }
1024+
9631025 #[ test]
9641026 fn test_conn_closed_read ( ) {
9651027 let io = AsyncIo :: new_buf ( vec ! [ ] , 0 ) ;
0 commit comments