humphrey/http/
proxy.rs

1//! Provides functionality for HTTP proxying.
2
3use crate::http::response::ResponseError;
4use crate::http::{Request, Response, StatusCode};
5
6use std::io::Write;
7use std::net::{SocketAddr, TcpStream};
8use std::time::Duration;
9
10/// Proxies a request to the given target, timing out and returning an error 502 after `timeout`.
11/// Always returns a response.
12pub fn proxy_request(request: &Request, target: SocketAddr, timeout: Duration) -> Response {
13    match proxy_request_internal(request, target, timeout) {
14        Ok(response) => response,
15        Err(_) => Response::empty(StatusCode::BadGateway)
16            .with_bytes(b"<html><body><h1>502 Bad Gateway</h1></body></html>"),
17    }
18}
19
20fn proxy_request_internal(
21    request: &Request,
22    target: SocketAddr,
23    timeout: Duration,
24) -> Result<Response, ResponseError> {
25    let mut stream =
26        TcpStream::connect_timeout(&target, timeout).map_err(|_| ResponseError::Stream)?;
27
28    let mut cloned_request = request.clone();
29    cloned_request
30        .headers
31        .add("X-Forwarded-For", request.address.origin_addr.to_string());
32    let request_bytes: Vec<u8> = cloned_request.into();
33    stream
34        .write_all(&request_bytes)
35        .map_err(|_| ResponseError::Stream)?;
36
37    Response::from_stream(&mut stream)
38}