Skip to main content

ingress_core/
lib.rs

1use chrono::{DateTime, Utc};
2use http::{HeaderMap, Method};
3use serde::{Deserialize, Serialize};
4use std::net::IpAddr;
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub enum GatewayKind {
8    Caddy,
9    Nginx,
10    Traefik,
11    Unknown,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct GatewayMetadata {
16    pub kind: GatewayKind,
17    pub adapter_version: String,
18    pub raw_forwarded_for: Option<String>,
19}
20
21impl GatewayMetadata {
22    pub fn new(kind: GatewayKind, adapter_version: impl Into<String>) -> Self {
23        Self {
24            kind,
25            adapter_version: adapter_version.into(),
26            raw_forwarded_for: None,
27        }
28    }
29}
30
31#[derive(Debug, Clone, Default, Serialize, Deserialize)]
32pub struct AuthContext {
33    pub is_authenticated: bool,
34    pub subject_id: Option<String>,
35    pub email: Option<String>,
36    pub groups: Vec<String>,
37    pub provider: Option<String>,
38}
39
40#[derive(Debug, Clone)]
41pub struct RequestContext {
42    pub request_id: String,
43    pub received_at: DateTime<Utc>,
44    pub method: Method,
45    pub path: String,
46    pub normalized_path: String,
47    pub query: Option<String>,
48    pub headers: HeaderMap,
49    pub client_ip: IpAddr,
50    pub scheme: String,
51    pub host: String,
52    pub user_agent: Option<String>,
53    pub auth: AuthContext,
54    pub gateway: GatewayKind,
55}
56
57pub type CanonicalRequestContext = RequestContext;
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub enum DecisionAction {
61    Allow,
62    Block,
63    RateLimit,
64    Shadow,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct RateLimitStatus {
69    pub remaining: u32,
70    pub reset_at_unix: i64,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct Decision {
75    pub action: DecisionAction,
76    pub reason_codes: Vec<String>,
77    pub matched_rule_ids: Vec<String>,
78    pub rate_limit_status: Option<RateLimitStatus>,
79}
80
81impl Decision {
82    pub fn allow(reason: impl Into<String>) -> Self {
83        Self {
84            action: DecisionAction::Allow,
85            reason_codes: vec![reason.into()],
86            matched_rule_ids: Vec::new(),
87            rate_limit_status: None,
88        }
89    }
90
91    pub fn block(reason: impl Into<String>, rule_id: impl Into<String>) -> Self {
92        Self {
93            action: DecisionAction::Block,
94            reason_codes: vec![reason.into()],
95            matched_rule_ids: vec![rule_id.into()],
96            rate_limit_status: None,
97        }
98    }
99
100    pub fn shadow(reason: impl Into<String>, rule_id: impl Into<String>) -> Self {
101        Self {
102            action: DecisionAction::Shadow,
103            reason_codes: vec![reason.into()],
104            matched_rule_ids: vec![rule_id.into()],
105            rate_limit_status: None,
106        }
107    }
108
109    pub fn rate_limit(
110        reason: impl Into<String>,
111        rule_id: impl Into<String>,
112        remaining: u32,
113        reset_at_unix: i64,
114    ) -> Self {
115        Self {
116            action: DecisionAction::RateLimit,
117            reason_codes: vec![reason.into()],
118            matched_rule_ids: vec![rule_id.into()],
119            rate_limit_status: Some(RateLimitStatus {
120                remaining,
121                reset_at_unix,
122            }),
123        }
124    }
125}