//! Support for BunnyCDN.

use log::*;
use trillium::{Handler, KnownHeaderName};

use crate::options::ServerOptions;

/// Update headers and request information based on BunnyCDN headers.
struct BunnyCDNHandler {
    options: &'static ServerOptions,
}

pub fn bunny_headers(options: &'static ServerOptions) -> impl Handler {
    BunnyCDNHandler { options }
}

#[trillium::async_trait]
impl Handler for BunnyCDNHandler {
    async fn run(&self, conn: trillium::Conn) -> trillium::Conn {
        let is_bunny = conn
            .request_headers()
            .get(KnownHeaderName::Via)
            .map(|h| h.as_ref() == b"BunnyCDN")
            .unwrap_or(false);
        if !is_bunny {
            return conn;
        }

        debug!("checking bunny authentication");
        let valid_bunny = if let Some(secret) = &self.options.cdn_secret {
            conn.request_headers()
                .get("x-opserve-auth")
                .map(|h| h.as_ref() == secret.as_bytes())
                .unwrap_or(false)
        } else {
            true
        };
        if !valid_bunny {
            warn!("BunnyCDN request failed authentication");
            return conn;
        }

        let mut conn = conn;
        let hdr = conn.request_headers_mut();
        if let Some(h) = hdr.get("cdn-host") {
            hdr.insert(KnownHeaderName::Host, h.clone());
        };
        conn
    }
}
