@@ -1737,6 +1737,151 @@ async fn http_connect_new() {
1737
1737
assert_eq ! ( s( & vec) , "bar=foo" ) ;
1738
1738
}
1739
1739
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
+
1740
1885
#[ tokio:: test]
1741
1886
async fn h2_connect ( ) {
1742
1887
let ( listener, addr) = setup_tcp_listener ( ) ;
0 commit comments