1use std::sync::atomic::{AtomicU64, Ordering};
2
3use serde::{Deserialize, Serialize};
4
5static NEXT_ID: AtomicU64 = AtomicU64::new(1);
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct StoredRequest {
9 pub id: u64,
10 pub port: u16,
11 pub method: String,
12 pub path: String,
13 pub raw_headers: String,
14 pub body_b64: String,
15}
16
17fn store_path() -> std::path::PathBuf {
18 std::env::temp_dir().join("tnnl-requests.jsonl")
19}
20
21pub fn init() {
22 let max = read_all().into_iter().map(|r| r.id).max().unwrap_or(0);
23 NEXT_ID.store(max + 1, Ordering::Relaxed);
24}
25
26pub fn next_id() -> u64 {
27 NEXT_ID.fetch_add(1, Ordering::Relaxed)
28}
29
30pub fn store(req: StoredRequest) {
31 let Ok(mut f) = std::fs::OpenOptions::new()
32 .create(true)
33 .append(true)
34 .open(store_path())
35 else {
36 return;
37 };
38 if let Ok(line) = serde_json::to_string(&req) {
39 use std::io::Write;
40 let _ = writeln!(f, "{line}");
41 }
42}
43
44pub fn find(id: u64) -> Option<StoredRequest> {
45 read_all().into_iter().find(|r| r.id == id)
46}
47
48fn read_all() -> Vec<StoredRequest> {
49 let Ok(content) = std::fs::read_to_string(store_path()) else {
50 return vec![];
51 };
52 content
53 .lines()
54 .filter_map(|l| serde_json::from_str(l).ok())
55 .collect()
56}