use osproxy_core::{Epoch, Target};
use crate::request::Protocol;
use crate::rules::{DocIdRule, InjectedField};
#[non_exhaustive]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum HeaderOp {
Add {
name: String,
value: String,
},
Remove {
name: String,
},
Replace {
name: String,
value: String,
},
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum BodyTransform {
None,
Inject(Vec<InjectedField>),
ConstructId(DocIdRule),
Both {
inject: Vec<InjectedField>,
id: DocIdRule,
},
}
impl BodyTransform {
#[must_use]
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct RouteDecision {
pub target: Target,
pub upstream_protocol: Protocol,
pub header_ops: Vec<HeaderOp>,
pub body_transform: BodyTransform,
pub epoch: Epoch,
}
impl RouteDecision {
#[must_use]
pub fn passthrough(target: Target, upstream_protocol: Protocol, epoch: Epoch) -> Self {
Self {
target,
upstream_protocol,
header_ops: Vec::new(),
body_transform: BodyTransform::None,
epoch,
}
}
#[must_use]
pub fn with_body_transform(mut self, transform: BodyTransform) -> Self {
self.body_transform = transform;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use osproxy_core::{ClusterId, IndexName};
fn target() -> Target {
Target::new(ClusterId::from("c"), IndexName::from("i"))
}
#[test]
fn passthrough_has_no_transform() {
let d = RouteDecision::passthrough(target(), Protocol::Http1, Epoch::ZERO);
assert!(d.body_transform.is_none());
assert!(d.header_ops.is_empty());
assert_eq!(d.epoch, Epoch::ZERO);
}
#[test]
fn body_transform_can_be_attached() {
let d = RouteDecision::passthrough(target(), Protocol::Http1, Epoch::new(2))
.with_body_transform(BodyTransform::Inject(vec![]));
assert!(!d.body_transform.is_none());
}
}