perimeterx-fastly-enforcer 2.2.2

PerimeterX Fastly Compute@Edge Rust Enforcer
Documentation
use crate::pxconfig::PXConfig;
use crate::pxcontext::PXContext;
use fastly::Response;

pub const PXHD_COOKIE_NAME: &str = "_pxhd";
pub const PXHD_MAX_AGE_SECS: u32 = 31_536_000;

/// Build a single `Set-Cookie` header value for `_pxhd`.
pub fn build_pxhd_set_cookie_value(
    pxhd: &str,
    pxhd_domain: Option<&str>,
    secured_pxhd_enabled: bool,
) -> String {
    let mut cookie =
        format!("{PXHD_COOKIE_NAME}={pxhd}; Max-Age={PXHD_MAX_AGE_SECS}; SameSite=Lax; Path=/");
    if let Some(domain) = pxhd_domain.filter(|d| !d.is_empty()) {
        cookie.push_str("; Domain=");
        cookie.push_str(domain);
    }
    if secured_pxhd_enabled {
        cookie.push_str("; Secure");
    }
    cookie
}

/// Resolve the `_pxhd` cookie `Domain` attribute: config override wins over Risk API.
pub(crate) fn resolve_pxhd_cookie_domain<'a>(
    conf: &'a PXConfig,
    ctx: &'a PXContext,
) -> Option<&'a str> {
    if !conf.pxhd_domain.is_empty() {
        Some(conf.pxhd_domain.as_str())
    } else {
        ctx.get_pxhd_domain()
    }
}

/// Append `_pxhd` `Set-Cookie` to `resp` when the context has a pxhd risk value.
pub fn apply_pxhd_cookie(resp: &mut Response, ctx: &PXContext, conf: &PXConfig) {
    let Some(pxhd) = ctx.get_pxhd_risk() else {
        return;
    };
    let domain = resolve_pxhd_cookie_domain(conf, ctx);
    let cookie = build_pxhd_set_cookie_value(pxhd, domain, conf.secured_pxhd_enabled);
    resp.append_header("set-cookie", cookie);
}