@@ -1737,6 +1737,151 @@ async fn http_connect_new() {
17371737 assert_eq ! ( s( & vec) , "bar=foo" ) ;
17381738}
17391739
1740+ struct UnhealthyBody {
1741+ rx : oneshot:: Receiver < ( ) > ,
1742+ tx : Option < oneshot:: Sender < ( ) > > ,
1743+ }
1744+
1745+ impl Body for UnhealthyBody {
1746+ type Data = Bytes ;
1747+
1748+ type Error = & ' static str ;
1749+
1750+ fn poll_frame (
1751+ self : Pin < & mut Self > ,
1752+ _cx : & mut Context < ' _ > ,
1753+ ) -> Poll < Option < Result < http_body:: Frame < Self :: Data > , Self :: Error > > > {
1754+ Poll :: Ready ( Some ( Ok ( http_body:: Frame :: data ( Bytes :: from_static (
1755+ & [ 0 ; 1024 ] ,
1756+ ) ) ) ) )
1757+ }
1758+
1759+ fn poll_healthy ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Result < ( ) , Self :: Error > {
1760+ if Pin :: new ( & mut self . rx ) . poll ( cx) . is_pending ( ) {
1761+ return Ok ( ( ) ) ;
1762+ }
1763+
1764+ let _ = self . tx . take ( ) . unwrap ( ) . send ( ( ) ) ;
1765+ Err ( "blammo" )
1766+ }
1767+ }
1768+
1769+ #[ tokio:: test]
1770+ async fn h1_unhealthy_body ( ) {
1771+ let ( listener, addr) = setup_tcp_listener ( ) ;
1772+ let ( unhealthy_tx, unhealthy_rx) = oneshot:: channel ( ) ;
1773+ let ( read_body_tx, read_body_rx) = oneshot:: channel ( ) ;
1774+
1775+ let client = tokio:: spawn ( async move {
1776+ let mut tcp = connect_async ( addr) . await ;
1777+ tcp. write_all (
1778+ b"\
1779+ GET / HTTP/1.1\r \n \
1780+ \r \n \
1781+ Host: localhost\r \n \
1782+ \r \n
1783+ " ,
1784+ )
1785+ . await
1786+ . expect ( "write 1" ) ;
1787+
1788+ let mut buf = [ 0 ; 1024 ] ;
1789+ loop {
1790+ let nread = tcp. read ( & mut buf) . await . expect ( "read 1" ) ;
1791+ if buf[ ..nread] . contains ( & 0 ) {
1792+ break ;
1793+ }
1794+ }
1795+
1796+ read_body_tx. send ( ( ) ) . unwrap ( ) ;
1797+ unhealthy_rx. await . expect ( "rx" ) ;
1798+
1799+ while tcp. read ( & mut buf) . await . expect ( "read" ) > 0 { }
1800+ } ) ;
1801+
1802+ let mut read_body_rx = Some ( read_body_rx) ;
1803+ let mut unhealthy_tx = Some ( unhealthy_tx) ;
1804+ let svc = service_fn ( move |_: Request < IncomingBody > | {
1805+ future:: ok :: < _ , & ' static str > (
1806+ Response :: builder ( )
1807+ . status ( 200 )
1808+ . body ( UnhealthyBody {
1809+ rx : read_body_rx. take ( ) . unwrap ( ) ,
1810+ tx : unhealthy_tx. take ( ) ,
1811+ } )
1812+ . unwrap ( ) ,
1813+ )
1814+ } ) ;
1815+
1816+ let ( socket, _) = listener. accept ( ) . await . unwrap ( ) ;
1817+ let err = http1:: Builder :: new ( )
1818+ . serve_connection ( socket, svc)
1819+ . await
1820+ . err ( )
1821+ . unwrap ( ) ;
1822+ assert ! ( err. to_string( ) . contains( "blammo" ) ) ;
1823+
1824+ client. await . unwrap ( ) ;
1825+ }
1826+
1827+ #[ tokio:: test]
1828+ async fn h2_unhealthy_body ( ) {
1829+ let ( listener, addr) = setup_tcp_listener ( ) ;
1830+ let ( unhealthy_tx, unhealthy_rx) = oneshot:: channel ( ) ;
1831+ let ( read_body_tx, read_body_rx) = oneshot:: channel ( ) ;
1832+
1833+ let client = tokio:: spawn ( async move {
1834+ let tcp = connect_async ( addr) . await ;
1835+ let ( h2, connection) = h2:: client:: handshake ( tcp) . await . unwrap ( ) ;
1836+ tokio:: spawn ( async move {
1837+ connection. await . unwrap ( ) ;
1838+ } ) ;
1839+ let mut h2 = h2. ready ( ) . await . unwrap ( ) ;
1840+
1841+ let request = Request :: get ( "/" ) . body ( ( ) ) . unwrap ( ) ;
1842+ let ( response, _) = h2. send_request ( request, true ) . unwrap ( ) ;
1843+
1844+ let mut body = response. await . unwrap ( ) . into_body ( ) ;
1845+
1846+ let bytes = body. data ( ) . await . unwrap ( ) . unwrap ( ) ;
1847+ let _ = body. flow_control ( ) . release_capacity ( bytes. len ( ) ) ;
1848+
1849+ read_body_tx. send ( ( ) ) . unwrap ( ) ;
1850+ unhealthy_rx. await . unwrap ( ) ;
1851+
1852+ loop {
1853+ let bytes = match body. data ( ) . await . transpose ( ) {
1854+ Ok ( Some ( bytes) ) => bytes,
1855+ Ok ( None ) => panic ! ( ) ,
1856+ Err ( _) => break ,
1857+ } ;
1858+ let _ = body. flow_control ( ) . release_capacity ( bytes. len ( ) ) ;
1859+ }
1860+ } ) ;
1861+
1862+ let mut read_body_rx = Some ( read_body_rx) ;
1863+ let mut unhealthy_tx = Some ( unhealthy_tx) ;
1864+ let svc = service_fn ( move |_: Request < IncomingBody > | {
1865+ future:: ok :: < _ , & ' static str > (
1866+ Response :: builder ( )
1867+ . status ( 200 )
1868+ . body ( UnhealthyBody {
1869+ rx : read_body_rx. take ( ) . unwrap ( ) ,
1870+ tx : unhealthy_tx. take ( ) ,
1871+ } )
1872+ . unwrap ( ) ,
1873+ )
1874+ } ) ;
1875+
1876+ let ( socket, _) = listener. accept ( ) . await . unwrap ( ) ;
1877+ http2:: Builder :: new ( TokioExecutor )
1878+ . serve_connection ( socket, svc)
1879+ . await
1880+ . unwrap ( ) ;
1881+
1882+ client. await . unwrap ( ) ;
1883+ }
1884+
17401885#[ tokio:: test]
17411886async fn h2_connect ( ) {
17421887 let ( listener, addr) = setup_tcp_listener ( ) ;
0 commit comments