Refactor proxy routing and session management

This commit is contained in:
2026-07-08 00:09:38 +03:00
parent c5bdb10445
commit b45dd2ae05
26 changed files with 5193 additions and 307 deletions

View File

@@ -1,5 +1,7 @@
use crate::activity::{append_activity, cap_activity, DEFAULT_ACTIVITY_LIMIT};
use crate::models::{ActivityEntry, ComponentStatus, Profile, Target};
use crate::models::{
ActivityEntry, ComponentStatus, LocalSingBoxConfig, Profile, SubscriptionCache, Target,
};
use serde::{de::DeserializeOwned, Serialize};
use std::fs;
use std::io::{self, ErrorKind};
@@ -18,6 +20,8 @@ pub struct StoragePaths {
pub profiles_file: PathBuf,
pub targets_file: PathBuf,
pub components_file: PathBuf,
pub local_singbox_file: PathBuf,
pub singbox_subscription_cache_file: PathBuf,
pub activity_file: PathBuf,
}
@@ -33,6 +37,8 @@ impl StoragePaths {
profiles_file: config_dir.join("profiles.json"),
targets_file: config_dir.join("targets.json"),
components_file: config_dir.join("components.json"),
local_singbox_file: config_dir.join("local-singbox.json"),
singbox_subscription_cache_file: state_dir.join("singbox-subscription-cache.json"),
activity_file: state_dir.join("activity.json"),
config_dir,
state_dir,
@@ -100,6 +106,30 @@ impl JsonStorage {
self.write_json(&self.paths.components_file, components)
}
pub fn read_local_singbox_config(&self) -> io::Result<LocalSingBoxConfig> {
self.read_json_or_default(&self.paths.local_singbox_file)
}
pub fn write_local_singbox_config(&self, config: &LocalSingBoxConfig) -> io::Result<()> {
self.write_json(&self.paths.local_singbox_file, config)
}
pub fn read_singbox_subscription_cache(&self) -> io::Result<Option<SubscriptionCache>> {
self.read_optional_json(&self.paths.singbox_subscription_cache_file)
}
pub fn write_singbox_subscription_cache(&self, cache: &SubscriptionCache) -> io::Result<()> {
self.write_json(&self.paths.singbox_subscription_cache_file, cache)
}
pub fn remove_singbox_subscription_cache(&self) -> io::Result<()> {
match fs::remove_file(&self.paths.singbox_subscription_cache_file) {
Ok(()) => Ok(()),
Err(error) if error.kind() == ErrorKind::NotFound => Ok(()),
Err(error) => Err(error),
}
}
pub fn read_activity(&self) -> io::Result<Vec<ActivityEntry>> {
let entries = self.read_json_or_default(&self.paths.activity_file)?;
Ok(cap_activity(entries, self.activity_limit))
@@ -139,6 +169,17 @@ impl JsonStorage {
.map_err(|error| io::Error::new(ErrorKind::InvalidData, error))?;
write_atomic(path, &contents)
}
fn read_optional_json<T>(&self, path: &Path) -> io::Result<Option<T>>
where
T: DeserializeOwned,
{
match fs::read_to_string(path) {
Ok(contents) => Ok(serde_json::from_str(&contents).ok()),
Err(error) if error.kind() == ErrorKind::NotFound => Ok(None),
Err(error) => Err(error),
}
}
}
impl Default for JsonStorage {