(
request_method: &str,
upstream: &mut U,
client: &mut C,
options: RelayResponseOptions,
)
| 1915 | } |
| 1916 | |
| 1917 | async fn relay_response<U, C>( |
| 1918 | request_method: &str, |
| 1919 | upstream: &mut U, |
| 1920 | client: &mut C, |
| 1921 | options: RelayResponseOptions, |
| 1922 | ) -> Result<RelayOutcome> |
| 1923 | where |
| 1924 | U: AsyncRead + Unpin, |
| 1925 | C: AsyncWrite + Unpin, |
| 1926 | { |
| 1927 | let started_at = std::time::Instant::now(); |
| 1928 | let mut buf = Vec::with_capacity(4096); |
| 1929 | let mut tmp = [0u8; 1024]; |
| 1930 | |
| 1931 | // Read response headers |
| 1932 | loop { |
| 1933 | if buf.len() > MAX_HEADER_BYTES { |
| 1934 | return Err(miette!("HTTP response headers exceed limit")); |
| 1935 | } |
| 1936 | |
| 1937 | let n = upstream.read(&mut tmp).await.into_diagnostic()?; |
| 1938 | if n == 0 { |
| 1939 | // Upstream closed — forward whatever we have |
| 1940 | if !buf.is_empty() { |
| 1941 | client.write_all(&buf).await.into_diagnostic()?; |
| 1942 | } |
| 1943 | return Ok(RelayOutcome::Consumed); |
| 1944 | } |
| 1945 | buf.extend_from_slice(&tmp[..n]); |
| 1946 | |
| 1947 | if buf.windows(4).any(|w| w == b"\r\n\r\n") { |
| 1948 | break; |
| 1949 | } |
| 1950 | } |
| 1951 | |
| 1952 | let header_end = buf.windows(4).position(|w| w == b"\r\n\r\n").unwrap() + 4; |
| 1953 | |
| 1954 | // Parse response framing |
| 1955 | let header_str = String::from_utf8_lossy(&buf[..header_end]); |
| 1956 | let status_code = parse_status_code(&header_str).unwrap_or(200); |
| 1957 | let server_wants_close = parse_connection_close(&header_str); |
| 1958 | let event_stream = response_is_event_stream(&header_str); |
| 1959 | let body_length = parse_body_length(&header_str)?; |
| 1960 | |
| 1961 | debug!( |
| 1962 | status_code, |
| 1963 | ?body_length, |
| 1964 | server_wants_close, |
| 1965 | request_method, |
| 1966 | overflow_bytes = buf.len() - header_end, |
| 1967 | "relay_response framing" |
| 1968 | ); |
| 1969 | |
| 1970 | // 101 Switching Protocols: the connection has been upgraded (e.g. to |
| 1971 | // WebSocket). Forward the 101 headers to the client and signal the |
| 1972 | // caller to switch to raw bidirectional TCP relay. Any bytes read |
| 1973 | // from upstream beyond the headers are overflow that belong to the |
| 1974 | // upgraded protocol and must be forwarded before switching. |
no test coverage detected