use std::fmt::Display;
use crate::constants::DEFAULT_NAMESPACE;
pub use super::route_match::*;
use serde::{Deserialize, Serialize};
use super::{gateway::SgBackendProtocol, PluginInstanceId};
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
#[serde(default)]
pub struct SgHttpRoute<P = PluginInstanceId> {
pub route_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub hostnames: Option<Vec<String>>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub plugins: Vec<P>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub rules: Vec<SgHttpRouteRule<P>>,
pub priority: i16,
}
impl<P> SgHttpRoute<P> {
pub fn map_plugins<F, T>(self, mut f: F) -> SgHttpRoute<T>
where
F: FnMut(P) -> T,
{
SgHttpRoute {
route_name: self.route_name,
hostnames: self.hostnames,
plugins: self.plugins.into_iter().map(&mut f).collect(),
rules: self.rules.into_iter().map(|rule| rule.map_plugins(&mut f)).collect(),
priority: self.priority,
}
}
}
impl<P> Default for SgHttpRoute<P> {
fn default() -> Self {
Self {
route_name: Default::default(),
hostnames: Default::default(),
plugins: Default::default(),
rules: Default::default(),
priority: 1,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
#[serde(default)]
pub struct SgHttpRouteRule<P = PluginInstanceId> {
#[serde(skip_serializing_if = "Option::is_none")]
pub matches: Option<Vec<SgHttpRouteMatch>>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub plugins: Vec<P>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub backends: Vec<SgBackendRef<P>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout_ms: Option<u32>,
}
impl<P> SgHttpRouteRule<P> {
pub fn map_plugins<F, T>(self, mut f: F) -> SgHttpRouteRule<T>
where
F: FnMut(P) -> T,
{
SgHttpRouteRule {
matches: self.matches,
plugins: self.plugins.into_iter().map(&mut f).collect(),
backends: self.backends.into_iter().map(|backend| backend.map_plugins(&mut f)).collect(),
timeout_ms: self.timeout_ms,
}
}
}
impl<P> Default for SgHttpRouteRule<P> {
fn default() -> Self {
Self {
matches: Default::default(),
plugins: Default::default(),
backends: Default::default(),
timeout_ms: Default::default(),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
#[serde(default)]
pub struct SgBackendRef<P = PluginInstanceId> {
pub host: BackendHost,
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout_ms: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub protocol: Option<SgBackendProtocol>,
#[serde(skip_serializing_if = "Option::is_none")]
pub downgrade_http2: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub weight: Option<u16>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub plugins: Vec<P>,
}
impl<P> SgBackendRef<P> {
pub fn map_plugins<F, T>(self, f: F) -> SgBackendRef<T>
where
F: FnMut(P) -> T,
{
SgBackendRef {
host: self.host,
port: self.port,
timeout_ms: self.timeout_ms,
protocol: self.protocol,
downgrade_http2: self.downgrade_http2,
weight: self.weight,
plugins: self.plugins.into_iter().map(f).collect(),
}
}
pub fn get_host(&self) -> String {
self.host.to_string()
}
}
impl<P> Default for SgBackendRef<P> {
fn default() -> Self {
Self {
host: Default::default(),
port: Default::default(),
timeout_ms: Default::default(),
downgrade_http2: Default::default(),
protocol: Default::default(),
weight: Default::default(),
plugins: Default::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
pub struct K8sServiceData {
pub name: String,
#[serde(alias = "ns")]
pub namespace: Option<String>,
}
impl Display for K8sServiceData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.namespace {
Some(ref ns) => write!(f, "{}.{}", self.name, ns),
None => write!(f, "{}.{}", self.name, DEFAULT_NAMESPACE),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
#[serde(tag = "kind")]
pub enum BackendHost {
Host { host: String },
K8sService(K8sServiceData),
File { path: String },
}
impl Display for BackendHost {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Host { host } => write!(f, "{}", host),
Self::K8sService(k8s_service) => write!(f, "{}", k8s_service),
Self::File { path } => write!(f, "{}", path),
}
}
}
impl Default for BackendHost {
fn default() -> Self {
Self::Host { host: String::default() }
}
}