iocaine 2.2.0

The deadliest poison known to AI
Documentation
// SPDX-FileCopyrightText: 2025 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: MIT

use axum::http::HeaderMap;
use cookie::Cookie;
use roto::{Runtime, Val, roto_method};
use std::sync::Arc;

use crate::means_of_production::Error;

#[derive(Debug, Clone)]
pub struct Request {
    pub method: String,
    pub headers: HeaderMap,
    pub path: String,
}

pub fn register_request_type(runtime: &mut Runtime) -> Result<(), Error> {
    runtime
        .register_clone_type_with_name::<Request>("Request", "Representation of a HTTP request")?;

    #[roto_method(runtime, Request)]
    fn path(request: Val<Request>) -> Arc<str> {
        request.path.clone().into()
    }

    #[roto_method(runtime, Request)]
    fn method(request: Val<Request>) -> Arc<str> {
        request.method.clone().into()
    }

    #[roto_method(runtime, Request)]
    fn header(request: Val<Request>, name: Arc<str>) -> Arc<str> {
        let h = request.headers.get(name.to_string());
        let s = h.map(|v| String::from_utf8_lossy(v.as_bytes()));
        s.unwrap_or_default().into()
    }

    #[roto_method(runtime, Request)]
    fn cookie(request: Val<Request>, name: Arc<str>) -> Arc<str> {
        let Some(cookie_header) = request.headers.get("cookie") else {
            return "".into();
        };
        let cookie_header = match cookie_header.to_str() {
            Ok(v) => v,
            Err(e) => {
                tracing::error!(
                    { cookies = format!("{cookie_header:?}") },
                    "Unable to parse cookie header: {e}"
                );
                return "".into();
            }
        };
        for cookie in Cookie::split_parse(cookie_header) {
            let Ok(cookie) = cookie else {
                tracing::error!("Unable to parse cookie");
                return "".into();
            };
            if cookie.name() == name.as_ref() {
                return cookie.value().into();
            }
        }
        "".into()
    }

    Ok(())
}