use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Rule {
pub id: String,
pub name: String,
pub active: bool,
pub stage: RuleStage,
#[serde(default)]
pub priority: i32,
pub termination: RuleTermination,
pub filter: Filter,
pub actions: Vec<Action>,
pub constraints: Option<RuleConstraints>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleGroup {
pub id: String,
pub name: String,
pub active: bool,
pub rules: Vec<Rule>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum RuleStage {
Connect,
RequestHeaders,
RequestBody,
ResponseHeaders,
ResponseBody,
WebSocketMessage,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RuleTermination {
Continue,
Stop,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleConstraints {
pub timeout_ms: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "config")]
pub enum Filter {
All,
SrcIp(String), DstPort(u16),
Protocol(String),
TransparentMode(bool),
Url(StringMatcher),
Host(StringMatcher),
Path(StringMatcher),
Method(StringMatcher),
RequestHeader {
name: String,
value: Option<StringMatcher>,
},
ResponseHeader {
name: String,
value: Option<StringMatcher>,
},
StatusCode(u16),
ResponseBody(StringMatcher),
WebSocketMessage(StringMatcher),
And(Vec<Filter>),
Or(Vec<Filter>),
Not(Box<Filter>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "mode", content = "value")]
pub enum StringMatcher {
Exact(String),
Contains(String),
Prefix(String),
Suffix(String),
Regex(String),
Glob(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "config")]
pub enum Action {
Drop,
Abort,
Delay { ms: u64 },
Throttle { kbps: u64 },
Tag { key: String, value: String },
Inspect,
SetVariable { name: String, value: String },
RateLimit {
key: String,
limit: u32,
window_ms: u64,
},
RedirectIp {
target: String,
},
SetTtl {
ttl: u8,
},
ForwardPort {
target_host: String,
target_port: u16,
},
MockResponse {
status: u16,
headers: HashMap<String, String>,
body: Option<BodySource>,
},
MapLocal {
path: String,
content_type: Option<String>,
},
MapRemote {
url: String,
preserve_host: bool,
},
Redirect {
location: String,
status: u16,
},
AddRequestHeader {
name: String,
value: String,
},
UpdateRequestHeader {
name: String,
value: String,
add_if_missing: bool,
},
DeleteRequestHeader {
name: String,
},
AddResponseHeader {
name: String,
value: String,
},
UpdateResponseHeader {
name: String,
value: String,
add_if_missing: bool,
},
DeleteResponseHeader {
name: String,
},
SetRequestMethod {
method: String,
},
SetRequestUrl {
url: String,
},
SetRequestBody {
body: BodySource,
},
SetResponseStatus {
status: u16,
},
SetResponseBody {
body: BodySource,
},
TransformRequestBody {
transform: BodyTransform,
},
TransformResponseBody {
transform: BodyTransform,
},
MockWebSocketMessage {
direction: WebSocketDirection,
message: String,
},
DropWebSocketMessage,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum BodySource {
Text(String),
File(String),
Base64(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "config")]
pub enum BodyTransform {
RegexReplace { pattern: String, replacement: String },
JsonPathSet { path: String, value: String },
JsonPathDelete { path: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WebSocketDirection {
Incoming,
Outgoing,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleTrace {
pub flow_id: String,
pub summary: RuleTraceSummary,
pub events: Vec<RuleExecutionEvent>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum RuleTraceSummary {
NoMatch,
Modified { rule_ids: Vec<String> },
Terminated {
rule_id: String,
reason: TerminalReason,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TerminalReason {
Drop,
Abort,
Mock,
Redirect,
Inspect,
RateLimited,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleExecutionEvent {
pub rule_id: String,
pub stage: RuleStage,
pub matched: bool,
pub duration_us: u64,
pub outcome: RuleOutcome,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum RuleOutcome {
Skipped,
MatchedAndExecuted,
MatchedAndTerminated,
Failed(String),
}