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 use chio_test_support::prelude::*;
83
84 #[test]
85 fn new_session_defaults() {
86 let session = SessionContext::new("sess-001".to_string(), CallerIdentity::anonymous());
87 assert_eq!(session.session_id, "sess-001");
88 assert_eq!(session.request_count, 0);
89 assert_eq!(session.bytes_read, 0);
90 assert_eq!(session.delegation_depth, 0);
91 assert!(session.expires_at.is_none());
92 }
93
94 #[test]
95 fn expired_session() {
96 let mut session = SessionContext::new("sess-002".to_string(), CallerIdentity::anonymous());
97 session.expires_at = Some(0); assert!(session.is_expired());
99 }
100
101 #[test]
102 fn not_expired_when_no_expiry() {
103 let session = SessionContext::new("sess-003".to_string(), CallerIdentity::anonymous());
104 assert!(!session.is_expired());
105 }
106
107 #[test]
108 fn serde_roundtrip() {
109 let session = SessionContext::new("sess-004".to_string(), CallerIdentity::anonymous());
110 let json = serde_json::to_string(&session).test_unwrap();
111 let back: SessionContext = serde_json::from_str(&json).test_unwrap();
112 assert_eq!(back.session_id, "sess-004");
113 }
114}