@@ -2908,6 +2908,146 @@ mod conn {
29082908 assert_eq ! ( vec, b"bar=foo" ) ;
29092909 }
29102910
2911+ #[ tokio:: test]
2912+ async fn client_100_then_http09 ( ) {
2913+ let ( server, addr) = setup_std_test_server ( ) ;
2914+
2915+ thread:: spawn ( move || {
2916+ let mut sock = server. accept ( ) . unwrap ( ) . 0 ;
2917+ sock. set_read_timeout ( Some ( Duration :: from_secs ( 5 ) ) ) . unwrap ( ) ;
2918+ sock. set_write_timeout ( Some ( Duration :: from_secs ( 5 ) ) )
2919+ . unwrap ( ) ;
2920+ let mut buf = [ 0 ; 4096 ] ;
2921+ sock. read ( & mut buf) . expect ( "read 1" ) ;
2922+ sock. write_all (
2923+ b"\
2924+ HTTP/1.1 100 Continue\r \n \
2925+ Content-Type: text/plain\r \n \
2926+ Server: BaseHTTP/0.6 Python/3.12.5\r \n \
2927+ Date: Mon, 16 Dec 2024 03:08:27 GMT\r \n \
2928+ ",
2929+ )
2930+ . unwrap ( ) ;
2931+ // That it's separate writes is important to this test
2932+ thread:: sleep ( Duration :: from_millis ( 50 ) ) ;
2933+ sock. write_all (
2934+ b"\
2935+ \r \n \
2936+ ",
2937+ )
2938+ . expect ( "write 2" ) ;
2939+ thread:: sleep ( Duration :: from_millis ( 50 ) ) ;
2940+ sock. write_all (
2941+ b"\
2942+ This is a sample text/plain document, without final headers.\
2943+ \n \n \
2944+ ",
2945+ )
2946+ . expect ( "write 3" ) ;
2947+ } ) ;
2948+
2949+ let tcp = tcp_connect ( & addr) . await . unwrap ( ) ;
2950+
2951+ let ( mut client, conn) = conn:: http1:: Builder :: new ( )
2952+ . http09_responses ( true )
2953+ . handshake ( tcp)
2954+ . await
2955+ . unwrap ( ) ;
2956+
2957+ tokio:: spawn ( async move {
2958+ let _ = conn. await ;
2959+ } ) ;
2960+
2961+ let req = Request :: builder ( )
2962+ . uri ( "/a" )
2963+ . body ( Empty :: < Bytes > :: new ( ) )
2964+ . unwrap ( ) ;
2965+ let _res = client. send_request ( req) . await . expect ( "send_request" ) ;
2966+ }
2967+
2968+ #[ tokio:: test]
2969+ async fn test_try_send_request ( ) {
2970+ use std:: future:: Future ;
2971+ let ( done_tx, done_rx) = tokio:: sync:: oneshot:: channel :: < ( ) > ( ) ;
2972+ let ( io_srv, io_cli) = tokio_test:: io:: Builder :: new ( )
2973+ . write ( b"GET / HTTP/1.1\r \n \r \n " )
2974+ . read ( b"HTTP/1.1 200 OK\r \n content-length: 0\r \n \r \n " )
2975+ . build_with_handle ( ) ;
2976+
2977+ tokio:: spawn ( async move {
2978+ let _io = io_cli;
2979+ let _ = done_rx. await ;
2980+ } ) ;
2981+
2982+ // make polling fair by putting both in spawns
2983+ tokio:: spawn ( async move {
2984+ let io = TokioIo :: new ( io_srv) ;
2985+ let ( mut client, mut conn) = conn:: http1:: Builder :: new ( )
2986+ . handshake :: < _ , Empty < Bytes > > ( io)
2987+ . await
2988+ . expect ( "http handshake" ) ;
2989+
2990+ // get the conn ready
2991+ assert ! (
2992+ future:: poll_fn( |cx| Poll :: Ready ( Pin :: new( & mut conn) . poll( cx) ) )
2993+ . await
2994+ . is_pending( )
2995+ ) ;
2996+ assert ! ( client. is_ready( ) ) ;
2997+
2998+ // use the connection once
2999+ let mut fut1 = std:: pin:: pin!( client. send_request( http:: Request :: new( Empty :: new( ) ) ) ) ;
3000+ let _res1 = future:: poll_fn ( |cx| loop {
3001+ if let Poll :: Ready ( res) = fut1. as_mut ( ) . poll ( cx) {
3002+ return Poll :: Ready ( res) ;
3003+ }
3004+ return match Pin :: new ( & mut conn) . poll ( cx) {
3005+ Poll :: Ready ( _) => panic ! ( "ruh roh" ) ,
3006+ Poll :: Pending => Poll :: Pending ,
3007+ } ;
3008+ } )
3009+ . await
3010+ . expect ( "resp 1" ) ;
3011+
3012+ assert ! ( client. is_ready( ) ) ;
3013+
3014+ // simulate the server dropping the conn
3015+ let _ = done_tx. send ( ( ) ) ;
3016+ // let the server task die
3017+ tokio:: task:: yield_now ( ) . await ;
3018+
3019+ let mut fut2 =
3020+ std:: pin:: pin!( client. try_send_request( http:: Request :: new( Empty :: new( ) ) ) ) ;
3021+ let poll1 = future:: poll_fn ( |cx| Poll :: Ready ( fut2. as_mut ( ) . poll ( cx) ) ) . await ;
3022+ assert ! ( poll1. is_pending( ) , "not already known to error" ) ;
3023+
3024+ let mut conn_opt = Some ( conn) ;
3025+ // wasn't a known error, req is in queue, and now the next poll, the
3026+ // conn will be noticed as errored
3027+ let mut err = future:: poll_fn ( |cx| {
3028+ loop {
3029+ if let Poll :: Ready ( res) = fut2. as_mut ( ) . poll ( cx) {
3030+ return Poll :: Ready ( res) ;
3031+ }
3032+ if let Some ( ref mut conn) = conn_opt {
3033+ match Pin :: new ( conn) . poll ( cx) {
3034+ Poll :: Ready ( _) => {
3035+ conn_opt = None ;
3036+ } // ok
3037+ Poll :: Pending => return Poll :: Pending ,
3038+ } ;
3039+ }
3040+ }
3041+ } )
3042+ . await
3043+ . expect_err ( "resp 2" ) ;
3044+
3045+ assert ! ( err. take_message( ) . is_some( ) , "request was returned" ) ;
3046+ } )
3047+ . await
3048+ . unwrap ( ) ;
3049+ }
3050+
29113051 #[ tokio:: test]
29123052 async fn http2_detect_conn_eof ( ) {
29133053 use futures_util:: future;
0 commit comments