atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
0cad5f1c5014fad20dca333ebdc5ed2aad545e32
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git

Blame: src/http/ctx.rs

8b8e83329a1datagen2026-10-12 12:01 UTC1
use std::{collections::HashMap, fmt::Write as _, time::Instant};
782069860236atagen2026-10-10 12:44 UTC2
782069860236atagen2026-10-10 12:44 UTC3
use axum::{
782069860236atagen2026-10-10 12:44 UTC4
    extract::{FromRequest, FromRequestParts, Query, RawPathParams, Request},
6619c458c23eatagen2026-10-14 08:08 UTC5
    http::{HeaderMap, HeaderName, Method, Uri, Version, header},
6619c458c23eatagen2026-10-14 08:08 UTC6
    response::Response,
782069860236atagen2026-10-10 12:44 UTC7
};
782069860236atagen2026-10-10 12:44 UTC8
use hyper::upgrade::OnUpgrade;
782069860236atagen2026-10-10 12:44 UTC9
782069860236atagen2026-10-10 12:44 UTC10
/// Everything a handler may look at, gathered once per request.
782069860236atagen2026-10-10 12:44 UTC11
pub struct Ctx {
8b8e83329a1datagen2026-10-12 12:01 UTC12
    method: Method,
8b8e83329a1datagen2026-10-12 12:01 UTC13
    uri: Uri,
8b8e83329a1datagen2026-10-12 12:01 UTC14
    version: Version,
8b8e83329a1datagen2026-10-12 12:01 UTC15
    headers: HeaderMap,
8b8e83329a1datagen2026-10-12 12:01 UTC16
    query: HashMap<String, String>,
8b8e83329a1datagen2026-10-12 12:01 UTC17
    params: HashMap<String, String>,
8b8e83329a1datagen2026-10-12 12:01 UTC18
    now: Instant,
8b8e83329a1datagen2026-10-12 12:01 UTC19
    upgrade: Option<OnUpgrade>,
782069860236atagen2026-10-10 12:44 UTC20
}
782069860236atagen2026-10-10 12:44 UTC21
782069860236atagen2026-10-10 12:44 UTC22
impl Ctx {
782069860236atagen2026-10-10 12:44 UTC23
    pub fn header(&self, name: HeaderName) -> Option<&str> {
782069860236atagen2026-10-10 12:44 UTC24
        self.headers.get(name).and_then(|v| v.to_str().ok())
782069860236atagen2026-10-10 12:44 UTC25
    }
782069860236atagen2026-10-10 12:44 UTC26
782069860236atagen2026-10-10 12:44 UTC27
    pub fn cookie(&self, name: &str) -> Option<&str> {
782069860236atagen2026-10-10 12:44 UTC28
        self.headers
782069860236atagen2026-10-10 12:44 UTC29
            .get_all(header::COOKIE)
782069860236atagen2026-10-10 12:44 UTC30
            .iter()
782069860236atagen2026-10-10 12:44 UTC31
            .filter_map(|v| v.to_str().ok())
782069860236atagen2026-10-10 12:44 UTC32
            .flat_map(|v| v.split(';'))
782069860236atagen2026-10-10 12:44 UTC33
            .filter_map(|pair| pair.trim().split_once('='))
782069860236atagen2026-10-10 12:44 UTC34
            .find(|(key, _)| *key == name)
782069860236atagen2026-10-10 12:44 UTC35
            .map(|(_, value)| value)
782069860236atagen2026-10-10 12:44 UTC36
    }
782069860236atagen2026-10-10 12:44 UTC37
782069860236atagen2026-10-10 12:44 UTC38
    pub fn param(&self, name: &str) -> &str {
782069860236atagen2026-10-10 12:44 UTC39
        self.params.get(name).map_or("", String::as_str)
782069860236atagen2026-10-10 12:44 UTC40
    }
782069860236atagen2026-10-10 12:44 UTC41
782069860236atagen2026-10-10 12:44 UTC42
    pub fn query(&self, name: &str) -> Option<&str> {
782069860236atagen2026-10-10 12:44 UTC43
        self.query.get(name).map(String::as_str)
782069860236atagen2026-10-10 12:44 UTC44
    }
8b8e83329a1datagen2026-10-12 12:01 UTC45
8b8e83329a1datagen2026-10-12 12:01 UTC46
    pub fn method(&self) -> &Method {
8b8e83329a1datagen2026-10-12 12:01 UTC47
        &self.method
8b8e83329a1datagen2026-10-12 12:01 UTC48
    }
8b8e83329a1datagen2026-10-12 12:01 UTC49
8b8e83329a1datagen2026-10-12 12:01 UTC50
    pub fn now(&self) -> Instant {
8b8e83329a1datagen2026-10-12 12:01 UTC51
        self.now
8b8e83329a1datagen2026-10-12 12:01 UTC52
    }
8b8e83329a1datagen2026-10-12 12:01 UTC53
8b8e83329a1datagen2026-10-12 12:01 UTC54
    pub fn take_upgrade(&mut self) -> Option<OnUpgrade> {
8b8e83329a1datagen2026-10-12 12:01 UTC55
        self.upgrade.take()
8b8e83329a1datagen2026-10-12 12:01 UTC56
    }
8b8e83329a1datagen2026-10-12 12:01 UTC57
8b8e83329a1datagen2026-10-12 12:01 UTC58
    /// The request as it arrived, which is what TRACE sends back.
8b8e83329a1datagen2026-10-12 12:01 UTC59
    pub fn echo(&self) -> String {
8b8e83329a1datagen2026-10-12 12:01 UTC60
        let mut message = format!("{} {} {:?}\r\n", self.method, self.uri, self.version);
8b8e83329a1datagen2026-10-12 12:01 UTC61
        for (name, value) in &self.headers {
8b8e83329a1datagen2026-10-12 12:01 UTC62
            let _ = write!(
8b8e83329a1datagen2026-10-12 12:01 UTC63
                message,
8b8e83329a1datagen2026-10-12 12:01 UTC64
                "{name}: {}\r\n",
8b8e83329a1datagen2026-10-12 12:01 UTC65
                value.to_str().unwrap_or("<binary>")
8b8e83329a1datagen2026-10-12 12:01 UTC66
            );
8b8e83329a1datagen2026-10-12 12:01 UTC67
        }
8b8e83329a1datagen2026-10-12 12:01 UTC68
        message.push_str("\r\n");
8b8e83329a1datagen2026-10-12 12:01 UTC69
        message
8b8e83329a1datagen2026-10-12 12:01 UTC70
    }
782069860236atagen2026-10-10 12:44 UTC71
}
782069860236atagen2026-10-10 12:44 UTC72
782069860236atagen2026-10-10 12:44 UTC73
impl<S: Send + Sync> FromRequest<S> for Ctx {
782069860236atagen2026-10-10 12:44 UTC74
    type Rejection = Response;
782069860236atagen2026-10-10 12:44 UTC75
782069860236atagen2026-10-10 12:44 UTC76
    async fn from_request(mut request: Request, state: &S) -> Result<Self, Self::Rejection> {
782069860236atagen2026-10-10 12:44 UTC77
        let upgrade = request.extensions_mut().remove::<OnUpgrade>();
6619c458c23eatagen2026-10-14 08:08 UTC78
        let (mut parts, _) = request.into_parts();
782069860236atagen2026-10-10 12:44 UTC79
        let params = RawPathParams::from_request_parts(&mut parts, state)
782069860236atagen2026-10-10 12:44 UTC80
            .await
782069860236atagen2026-10-10 12:44 UTC81
            .map(|raw| {
782069860236atagen2026-10-10 12:44 UTC82
                raw.iter()
782069860236atagen2026-10-10 12:44 UTC83
                    .map(|(k, v)| (k.to_owned(), v.to_owned()))
782069860236atagen2026-10-10 12:44 UTC84
                    .collect()
782069860236atagen2026-10-10 12:44 UTC85
            })
782069860236atagen2026-10-10 12:44 UTC86
            .unwrap_or_default();
782069860236atagen2026-10-10 12:44 UTC87
        let query = Query::<HashMap<String, String>>::try_from_uri(&parts.uri)
782069860236atagen2026-10-10 12:44 UTC88
            .map(|q| q.0)
782069860236atagen2026-10-10 12:44 UTC89
            .unwrap_or_default();
782069860236atagen2026-10-10 12:44 UTC90
        Ok(Self {
782069860236atagen2026-10-10 12:44 UTC91
            method: parts.method,
782069860236atagen2026-10-10 12:44 UTC92
            uri: parts.uri,
782069860236atagen2026-10-10 12:44 UTC93
            version: parts.version,
782069860236atagen2026-10-10 12:44 UTC94
            headers: parts.headers,
782069860236atagen2026-10-10 12:44 UTC95
            query,
782069860236atagen2026-10-10 12:44 UTC96
            params,
782069860236atagen2026-10-10 12:44 UTC97
            now: Instant::now(),
782069860236atagen2026-10-10 12:44 UTC98
            upgrade,
782069860236atagen2026-10-10 12:44 UTC99
        })
782069860236atagen2026-10-10 12:44 UTC100
    }
782069860236atagen2026-10-10 12:44 UTC101
}