Skip to main content

static_web_server/
custom_headers.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// This file is part of Static Web Server.
3// See https://static-web-server.net/ for more information
4// Copyright (C) 2019-present Jose Quintana <joseluisq.net>
5
6//! Module to append custom HTTP headers via TOML config file.
7//!
8
9use hyper::{Request, Response};
10use std::{ffi::OsStr, path::PathBuf};
11
12use crate::body::Body;
13use crate::{Error, handler::RequestHandlerOpts, settings::Headers};
14
15/// Appends custom HTTP headers to a response if necessary
16pub(crate) fn post_process<T>(
17    opts: &RequestHandlerOpts,
18    req: &Request<T>,
19    mut resp: Response<Body>,
20    file_path: Option<&PathBuf>,
21) -> Result<Response<Body>, Error> {
22    if let Some(advanced) = &opts.advanced_opts {
23        append_headers(
24            req.uri().path(),
25            advanced.headers.as_deref(),
26            &mut resp,
27            file_path,
28            opts.redirect_trailing_slash,
29        )
30    }
31    Ok(resp)
32}
33
34/// Append custom HTTP headers to current response.
35fn append_headers(
36    uri_path: &str,
37    headers_opts: Option<&[Headers]>,
38    resp: &mut Response<Body>,
39    file_path: Option<&PathBuf>,
40    redirect_trailing_slash: bool,
41) {
42    if let Some(headers_vec) = headers_opts {
43        let uri_path_auto_index = file_path
44            .filter(|_| uri_path.ends_with('/') || !redirect_trailing_slash)
45            .and_then(|p| p.file_name())
46            .and_then(OsStr::to_str)
47            .map(|name| match uri_path {
48                "/" => ["/", name].concat(),
49                _ => [uri_path, "/", name].concat(),
50            });
51
52        let uri_path = match uri_path_auto_index {
53            Some(ref s) => s.as_str(),
54            _ => uri_path,
55        };
56
57        for headers_entry in headers_vec {
58            // Match header glob pattern against request uri
59            if headers_entry.source.is_match(uri_path) {
60                // Add/update headers if uri matches
61                for (name, value) in &headers_entry.headers {
62                    resp.headers_mut().insert(name, value.to_owned());
63                }
64            }
65        }
66    }
67}