use std::collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
type HeaderName = String;
type RegExp = String;
pub const HOP_BY_HOP_HEADERS: &[&str] = &[
"connection",
"keep-alive",
"proxy-authenticate",
"proxy-authorization",
"te",
"trailer",
"transfer-encoding",
"upgrade",
"proxy-connection",
"host",
"content-length",
];
pub static NEVER_JOIN_HEADERS: &[&str] = &["set-cookie", "www-authenticate"];
#[derive(Debug, Default, Deserialize, Serialize, JsonSchema, Clone)]
#[schemars(example = headers_example_1())]
pub struct HeadersConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub all: Option<HeaderRules>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subgraphs: Option<HashMap<String, HeaderRules>>,
}
fn headers_example_1() -> HeadersConfig {
HeadersConfig {
all: Some(HeaderRules {
request: Some(vec![
RequestHeaderRule::Propagate(RequestPropagateRule {
spec: MatchSpec {
named: Some(OneOrMany::One("Authorization".to_string())),
..Default::default()
},
..Default::default()
}),
RequestHeaderRule::Remove(RemoveRule {
spec: MatchSpec {
matching: Some(OneOrMany::One("^x-legacy-.*".to_string())),
..Default::default()
},
}),
RequestHeaderRule::Insert(RequestInsertRule {
name: "x-router".to_string(),
source: InsertSource::Value {
value: "hive-router".to_string(),
},
}),
]),
response: None,
}),
subgraphs: Some(HashMap::from([(
"accounts".to_string(),
HeaderRules {
request: Some(vec![RequestHeaderRule::Propagate(RequestPropagateRule {
spec: MatchSpec {
named: Some(OneOrMany::One("x-tenant-id".to_string())),
..Default::default()
},
rename: Some("x-acct-tenant".to_string()),
default: Some("unknown".to_string()),
})]),
response: None,
},
)])),
}
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, Default)]
pub struct HeaderRules {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request: Option<Vec<RequestHeaderRule>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub response: Option<Vec<ResponseHeaderRule>>,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(rename_all = "snake_case")]
pub enum RequestHeaderRule {
Propagate(RequestPropagateRule),
Remove(RemoveRule),
Insert(RequestInsertRule),
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(rename_all = "snake_case")]
pub enum ResponseHeaderRule {
Propagate(ResponsePropagateRule),
Remove(RemoveRule),
Insert(ResponseInsertRule),
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
pub struct RemoveRule {
#[serde(flatten)]
pub spec: MatchSpec,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
pub struct RequestInsertRule {
pub name: HeaderName,
#[serde(flatten)]
pub source: InsertSource,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
pub struct ResponseInsertRule {
pub name: HeaderName,
#[serde(flatten)]
pub source: InsertSource,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub algorithm: Option<AggregationAlgo>,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(untagged)]
pub enum InsertSource {
Value { value: String },
Expression { expression: String },
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(untagged)]
pub enum OneOrMany<T> {
One(T),
Many(Vec<T>),
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, Default)]
pub struct MatchSpec {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub named: Option<OneOrMany<HeaderName>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub matching: Option<OneOrMany<RegExp>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub exclude: Option<Vec<RegExp>>,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, Default)]
pub struct RequestPropagateRule {
#[serde(flatten)]
pub spec: MatchSpec,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rename: Option<HeaderName>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, Copy)]
#[serde(rename_all = "snake_case")]
pub enum AggregationAlgo {
First,
Last,
Append,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
pub struct ResponsePropagateRule {
#[serde(flatten)]
pub spec: MatchSpec,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rename: Option<HeaderName>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default: Option<String>,
pub algorithm: AggregationAlgo,
}