@@ -74,6 +74,8 @@ pub struct HttpSession {
7474 digest : Box < Digest > ,
7575 /// Minimum send rate to the client
7676 min_send_rate : Option < usize > ,
77+ /// When this is enabled informational response headers will not be proxied downstream
78+ ignore_info_resp : bool ,
7779}
7880
7981impl HttpSession {
@@ -109,6 +111,7 @@ impl HttpSession {
109111 upgraded : false ,
110112 digest,
111113 min_send_rate : None ,
114+ ignore_info_resp : false ,
112115 }
113116 }
114117
@@ -388,6 +391,11 @@ impl HttpSession {
388391 /// Write the response header to the client.
389392 /// This function can be called more than once to send 1xx informational headers excluding 101.
390393 pub async fn write_response_header ( & mut self , mut header : Box < ResponseHeader > ) -> Result < ( ) > {
394+ if header. status . is_informational ( ) && self . ignore_info_resp ( header. status . into ( ) ) {
395+ debug ! ( "ignoring informational headers" ) ;
396+ return Ok ( ( ) ) ;
397+ }
398+
391399 if let Some ( resp) = self . response_written . as_ref ( ) {
392400 if !resp. status . is_informational ( ) || self . upgraded {
393401 warn ! ( "Respond header is already sent, cannot send again" ) ;
@@ -409,7 +417,7 @@ impl HttpSession {
409417 header. insert_header ( header:: CONNECTION , connection_value) ?;
410418 }
411419
412- if header. status . as_u16 ( ) == 101 {
420+ if header. status == 101 {
413421 // make sure the connection is closed at the end when 101/upgrade is used
414422 self . set_keepalive ( None ) ;
415423 }
@@ -510,6 +518,18 @@ impl HttpSession {
510518 ( None , None )
511519 }
512520
521+ fn ignore_info_resp ( & self , status : u16 ) -> bool {
522+ // ignore informational response if ignore flag is set and it's not an Upgrade and Expect: 100-continue isn't set
523+ self . ignore_info_resp && status != 101 && !( status == 100 && self . is_expect_continue_req ( ) )
524+ }
525+
526+ fn is_expect_continue_req ( & self ) -> bool {
527+ match self . request_header . as_deref ( ) {
528+ Some ( req) => is_expect_continue_req ( req) ,
529+ None => false ,
530+ }
531+ }
532+
513533 fn is_connection_keepalive ( & self ) -> Option < bool > {
514534 is_buf_keepalive ( self . get_header ( header:: CONNECTION ) )
515535 }
@@ -824,6 +844,14 @@ impl HttpSession {
824844 }
825845 }
826846
847+ /// Sets whether we ignore writing informational responses downstream.
848+ ///
849+ /// This is a noop if the response is Upgrade or Continue and
850+ /// Expect: 100-continue was set on the request.
851+ pub fn set_ignore_info_resp ( & mut self , ignore : bool ) {
852+ self . ignore_info_resp = ignore;
853+ }
854+
827855 /// Return the [Digest] of the connection.
828856 pub fn digest ( & self ) -> & Digest {
829857 & self . digest
@@ -1472,6 +1500,75 @@ mod tests_stream {
14721500 . unwrap ( ) ;
14731501 }
14741502
1503+ #[ tokio:: test]
1504+ async fn write_informational_ignored ( ) {
1505+ let wire = b"HTTP/1.1 200 OK\r \n Foo: Bar\r \n \r \n " ;
1506+ let mock_io = Builder :: new ( ) . write ( wire) . build ( ) ;
1507+ let mut http_stream = HttpSession :: new ( Box :: new ( mock_io) ) ;
1508+ // ignore the 100 Continue
1509+ http_stream. ignore_info_resp = true ;
1510+ let response_100 = ResponseHeader :: build ( StatusCode :: CONTINUE , None ) . unwrap ( ) ;
1511+ http_stream
1512+ . write_response_header_ref ( & response_100)
1513+ . await
1514+ . unwrap ( ) ;
1515+ let mut response_200 = ResponseHeader :: build ( StatusCode :: OK , None ) . unwrap ( ) ;
1516+ response_200. append_header ( "Foo" , "Bar" ) . unwrap ( ) ;
1517+ http_stream. update_resp_headers = false ;
1518+ http_stream
1519+ . write_response_header_ref ( & response_200)
1520+ . await
1521+ . unwrap ( ) ;
1522+ }
1523+
1524+ #[ tokio:: test]
1525+ async fn write_informational_100_not_ignored_if_expect_continue ( ) {
1526+ let input = b"GET / HTTP/1.1\r \n Expect: 100-continue\r \n \r \n " ;
1527+ let output = b"HTTP/1.1 100 Continue\r \n \r \n HTTP/1.1 200 OK\r \n Foo: Bar\r \n \r \n " ;
1528+
1529+ let mock_io = Builder :: new ( ) . read ( & input[ ..] ) . write ( output) . build ( ) ;
1530+ let mut http_stream = HttpSession :: new ( Box :: new ( mock_io) ) ;
1531+ http_stream. read_request ( ) . await . unwrap ( ) ;
1532+ http_stream. ignore_info_resp = true ;
1533+ // 100 Continue is not ignored due to Expect: 100-continue on request
1534+ let response_100 = ResponseHeader :: build ( StatusCode :: CONTINUE , None ) . unwrap ( ) ;
1535+ http_stream
1536+ . write_response_header_ref ( & response_100)
1537+ . await
1538+ . unwrap ( ) ;
1539+ let mut response_200 = ResponseHeader :: build ( StatusCode :: OK , None ) . unwrap ( ) ;
1540+ response_200. append_header ( "Foo" , "Bar" ) . unwrap ( ) ;
1541+ http_stream. update_resp_headers = false ;
1542+ http_stream
1543+ . write_response_header_ref ( & response_200)
1544+ . await
1545+ . unwrap ( ) ;
1546+ }
1547+
1548+ #[ tokio:: test]
1549+ async fn write_informational_1xx_ignored_if_expect_continue ( ) {
1550+ let input = b"GET / HTTP/1.1\r \n Expect: 100-continue\r \n \r \n " ;
1551+ let output = b"HTTP/1.1 200 OK\r \n Foo: Bar\r \n \r \n " ;
1552+
1553+ let mock_io = Builder :: new ( ) . read ( & input[ ..] ) . write ( output) . build ( ) ;
1554+ let mut http_stream = HttpSession :: new ( Box :: new ( mock_io) ) ;
1555+ http_stream. read_request ( ) . await . unwrap ( ) ;
1556+ http_stream. ignore_info_resp = true ;
1557+ // 102 Processing is ignored
1558+ let response_102 = ResponseHeader :: build ( StatusCode :: PROCESSING , None ) . unwrap ( ) ;
1559+ http_stream
1560+ . write_response_header_ref ( & response_102)
1561+ . await
1562+ . unwrap ( ) ;
1563+ let mut response_200 = ResponseHeader :: build ( StatusCode :: OK , None ) . unwrap ( ) ;
1564+ response_200. append_header ( "Foo" , "Bar" ) . unwrap ( ) ;
1565+ http_stream. update_resp_headers = false ;
1566+ http_stream
1567+ . write_response_header_ref ( & response_200)
1568+ . await
1569+ . unwrap ( ) ;
1570+ }
1571+
14751572 #[ tokio:: test]
14761573 async fn write_101_switching_protocol ( ) {
14771574 let wire = b"HTTP/1.1 101 Switching Protocols\r \n Foo: Bar\r \n \r \n " ;
0 commit comments