static_web_server/
https_redirect.rs1use headers::{HeaderMapExt, Host};
10use hyper::{header::LOCATION, Body, Request, Response, StatusCode};
11use std::sync::Arc;
12
13use crate::Result;
14
15pub struct RedirectOpts {
17 pub https_hostname: String,
19 pub https_port: u16,
21 pub allowed_hosts: Vec<String>,
23}
24
25pub fn redirect_to_https<T>(
27 req: &Request<T>,
28 opts: Arc<RedirectOpts>,
29) -> Result<Response<Body>, StatusCode> {
30 if let Some(ref host) = req.headers().typed_get::<Host>() {
31 let from_hostname = host.hostname();
32 if !opts
33 .allowed_hosts
34 .iter()
35 .any(|s| s.as_str() == from_hostname)
36 {
37 tracing::debug!("redirect host is not allowed!");
38 return Err(StatusCode::BAD_REQUEST);
39 }
40
41 let url = format!(
42 "https://{}:{}{}",
43 opts.https_hostname,
44 opts.https_port,
45 req.uri()
46 );
47 tracing::debug!("https redirect to {}", url);
48
49 let mut resp = Response::new(Body::empty());
50 *resp.status_mut() = StatusCode::MOVED_PERMANENTLY;
51 resp.headers_mut().insert(LOCATION, url.parse().unwrap());
52 return Ok(resp);
53 }
54
55 tracing::debug!("redirect host was not determined!");
56 Err(StatusCode::BAD_REQUEST)
57}