use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::Arc;
use hyper::body::Incoming;
use hyper::header::HeaderValue;
use hyper::{Request, Response, StatusCode};
use crate::ResponseBody;
use crate::ServerState;
use crate::body::box_incoming;
use crate::proxy::proxy_core;
use crate::respond::{fault, synth};
pub(crate) async fn handle(
state: Arc<ServerState>,
scheme: &'static str,
peer: SocketAddr,
req: Request<Incoming>,
) -> Result<Response<ResponseBody>, Infallible> {
let (parts, incoming) = req.into_parts();
let mut resp =
match proxy_core(state.clone(), scheme, peer, parts, box_incoming(incoming)).await {
Ok(resp) => resp,
Err(e) => {
tracing::warn!(error = %e, "fast-path error");
synth(StatusCode::BAD_GATEWAY, &fault::UPSTREAM, b"upstream error")
}
};
attach_alt_svc(&mut resp, state.alt_svc.as_ref());
Ok(resp)
}
pub(crate) fn attach_alt_svc(resp: &mut Response<ResponseBody>, alt_svc: Option<&HeaderValue>) {
if let Some(av) = alt_svc {
resp.headers_mut()
.insert(hyper::header::ALT_SVC, av.clone());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::body::full;
fn resp() -> Response<ResponseBody> {
Response::new(full(Vec::new()))
}
#[test]
fn attach_alt_svc_sets_the_header_when_configured() {
let mut r = resp();
let av = HeaderValue::from_static("h3=\":443\"; ma=86400");
attach_alt_svc(&mut r, Some(&av));
assert_eq!(r.headers().get(hyper::header::ALT_SVC), Some(&av));
}
#[test]
fn attach_alt_svc_is_a_noop_when_absent() {
let mut r = resp();
attach_alt_svc(&mut r, None);
assert!(r.headers().get(hyper::header::ALT_SVC).is_none());
}
}