diff --git a/Dockerfile b/Dockerfile index 41df609..3a6ebe7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.57-bullseye as builder +FROM rust:1.58-buster as builder RUN apt-get update && \ apt-get install -y libssl-dev pkg-config diff --git a/src/reverse_proxy.rs b/src/reverse_proxy.rs index c6e0bac..791b2d5 100644 --- a/src/reverse_proxy.rs +++ b/src/reverse_proxy.rs @@ -72,22 +72,34 @@ fn create_proxied_request( .uri(forward_uri(forward_url, &request)?) .version(hyper::Version::HTTP_11); - *builder.headers_mut().unwrap() = remove_hop_headers(request.headers()); + let headers = builder.headers_mut().unwrap(); + + *headers = remove_hop_headers(request.headers()); // If request does not have host header, add it from original URI authority - if let header::Entry::Vacant(entry) = builder.headers_mut().unwrap().entry(header::HOST) { + if let header::Entry::Vacant(entry) = headers.entry(header::HOST) { if let Some(authority) = request.uri().authority() { entry.insert(authority.as_str().parse()?); } } + // Concatenate cookie headers into single header + // (HTTP/2 allows several cookie headers, but we are proxying to + // HTTP/1.1 that does not) + let mut cookie_concat = vec![]; + while let Some(cookie) = headers.remove(header::COOKIE) { + if !cookie_concat.is_empty() { + cookie_concat.extend(b"; "); + } + cookie_concat.extend_from_slice(cookie.as_bytes()); + } + if !cookie_concat.is_empty() { + headers.insert(header::COOKIE, cookie_concat.try_into()?); + } + // Add forwarding information in the headers let x_forwarded_for_header_name = "x-forwarded-for"; - match builder - .headers_mut() - .unwrap() - .entry(x_forwarded_for_header_name) - { + match headers.entry(x_forwarded_for_header_name) { header::Entry::Vacant(entry) => { entry.insert(client_ip.to_string().parse()?); } @@ -98,7 +110,7 @@ fn create_proxied_request( } } - builder.headers_mut().unwrap().insert( + headers.insert( HeaderName::from_bytes(b"x-forwarded-proto")?, "https".try_into()?, ); @@ -107,14 +119,8 @@ fn create_proxied_request( if let Some(conn) = request.headers().get(header::CONNECTION) { if conn.to_str()?.to_lowercase() == "upgrade" { if let Some(upgrade) = request.headers().get(header::UPGRADE) { - builder - .headers_mut() - .unwrap() - .insert(header::CONNECTION, "Upgrade".try_into()?); - builder - .headers_mut() - .unwrap() - .insert(header::UPGRADE, upgrade.clone()); + headers.insert(header::CONNECTION, "Upgrade".try_into()?); + headers.insert(header::UPGRADE, upgrade.clone()); } } }