phantom_frame/
config.rs

1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3use std::path::Path;
4
5#[derive(Debug, Clone, Deserialize, Serialize)]
6pub struct Config {
7    pub server: ServerConfig,
8}
9
10#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct ServerConfig {
12    #[serde(default = "default_control_port")]
13    pub control_port: u16,
14
15    #[serde(default = "default_proxy_port")]
16    pub proxy_port: u16,
17
18    /// The URL of the backend to proxy to
19    #[serde(default = "default_proxy_url")]
20    pub proxy_url: String,
21
22    /// Paths to include in caching (empty means include all)
23    /// Supports wildcards: ["/api/*", "/*/users"]
24    #[serde(default)]
25    pub include_paths: Vec<String>,
26
27    /// Paths to exclude from caching (empty means exclude none)
28    /// Supports wildcards: ["/admin/*", "/*/private"]
29    /// Exclude overrides include
30    #[serde(default)]
31    pub exclude_paths: Vec<String>,
32
33    /// Enable WebSocket and protocol upgrade support (default: true)
34    /// When enabled, requests with Connection: Upgrade headers will bypass
35    /// the cache and establish a direct bidirectional TCP tunnel
36    #[serde(default = "default_enable_websocket")]
37    pub enable_websocket: bool,
38
39    /// Only allow GET requests, reject all others (default: false)
40    /// When true, only GET requests are processed; POST, PUT, DELETE, etc. return 405 Method Not Allowed
41    /// Useful for static site prerendering where mutations shouldn't be allowed
42    #[serde(default = "default_forward_get_only")]
43    pub forward_get_only: bool,
44
45    pub control_auth: Option<String>,
46
47    /// Capacity for the 404 cache (default: 100)
48    /// Limits the number of different 404 responses cached to prevent memory abuse
49    #[serde(default = "default_cache_404_capacity")]
50    pub cache_404_capacity: usize,
51
52    /// Detect 404 pages via meta tag in HTML body in addition to HTTP status
53    /// This lowers performance and should be enabled only when needed.
54    #[serde(default = "default_use_404_meta")]
55    pub use_404_meta: bool,
56}
57
58fn default_enable_websocket() -> bool {
59    true
60}
61
62fn default_forward_get_only() -> bool {
63    false
64}
65
66fn default_control_port() -> u16 {
67    17809
68}
69
70fn default_proxy_port() -> u16 {
71    3000
72}
73
74fn default_proxy_url() -> String {
75    "http://localhost:8080".to_string()
76}
77
78fn default_cache_404_capacity() -> usize {
79    100
80}
81
82fn default_use_404_meta() -> bool {
83    false
84}
85
86impl Config {
87    pub fn from_file(path: impl AsRef<Path>) -> Result<Self> {
88        let content = std::fs::read_to_string(path)?;
89        let config: Config = toml::from_str(&content)?;
90        Ok(config)
91    }
92}
93
94impl Default for ServerConfig {
95    fn default() -> Self {
96        Self {
97            control_port: default_control_port(),
98            proxy_port: default_proxy_port(),
99            proxy_url: default_proxy_url(),
100            include_paths: vec![],
101            exclude_paths: vec![],
102            enable_websocket: default_enable_websocket(),
103            forward_get_only: default_forward_get_only(),
104            control_auth: None,
105            cache_404_capacity: default_cache_404_capacity(),
106            use_404_meta: default_use_404_meta(),
107        }
108    }
109}