chio_http_core/
session.rs1use serde::{Deserialize, Serialize};
4
5use crate::identity::CallerIdentity;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct SessionContext {
12 pub session_id: String,
14
15 pub caller: CallerIdentity,
17
18 pub created_at: u64,
20
21 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub expires_at: Option<u64>,
25
26 #[serde(default)]
28 pub request_count: u64,
29
30 #[serde(default)]
32 pub bytes_read: u64,
33
34 #[serde(default)]
36 pub bytes_written: u64,
37
38 #[serde(default)]
40 pub delegation_depth: u32,
41
42 #[serde(default, skip_serializing_if = "Option::is_none")]
44 pub metadata: Option<serde_json::Value>,
45}
46
47impl SessionContext {
48 #[must_use]
50 pub fn new(session_id: String, caller: CallerIdentity) -> Self {
51 let now = chrono::Utc::now().timestamp() as u64;
52 Self {
53 session_id,
54 caller,
55 created_at: now,
56 expires_at: None,
57 request_count: 0,
58 bytes_read: 0,
59 bytes_written: 0,
60 delegation_depth: 0,
61 metadata: None,
62 }
63 }
64
65 #[must_use]
67 pub fn is_expired(&self) -> bool {
68 if let Some(exp) = self.expires_at {
69 let now = chrono::Utc::now().timestamp() as u64;
70 now >= exp
71 } else {
72 false
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::identity::CallerIdentity;
81
82 #[test]
83 fn new_session_defaults() {
84 let session = SessionContext::new("sess-001".to_string(), CallerIdentity::anonymous());
85 assert_eq!(session.session_id, "sess-001");
86 assert_eq!(session.request_count, 0);
87 assert_eq!(session.bytes_read, 0);
88 assert_eq!(session.delegation_depth, 0);
89 assert!(session.expires_at.is_none());
90 }
91
92 #[test]
93 fn expired_session() {
94 let mut session = SessionContext::new("sess-002".to_string(), CallerIdentity::anonymous());
95 session.expires_at = Some(0); assert!(session.is_expired());
97 }
98
99 #[test]
100 fn not_expired_when_no_expiry() {
101 let session = SessionContext::new("sess-003".to_string(), CallerIdentity::anonymous());
102 assert!(!session.is_expired());
103 }
104
105 #[test]
106 fn serde_roundtrip() {
107 let session = SessionContext::new("sess-004".to_string(), CallerIdentity::anonymous());
108 let json = serde_json::to_string(&session).unwrap();
109 let back: SessionContext = serde_json::from_str(&json).unwrap();
110 assert_eq!(back.session_id, "sess-004");
111 }
112}