use reqwest::header::{HeaderMap, HeaderValue};
use url::Url;
pub(crate) const BACKEND_HEADER: &str = "x-cf-integration-backend";
pub(crate) const DATAPLANE_BACKEND: &str = "dataplane";
pub(crate) const CONTROLPLANE_FALLBACK_BACKEND: &str = "controlplane-fallback";
pub(crate) const CONTROLPLANE_BACKEND: &str = "controlplane";
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum BackendIdentity {
Missing,
Dataplane,
ControlplaneFallback,
Controlplane,
Invalid,
Multiple,
}
impl BackendIdentity {
#[must_use]
pub(crate) fn from_headers(headers: &HeaderMap) -> Self {
let mut values = headers.get_all(BACKEND_HEADER).iter();
let Some(value) = values.next() else {
return Self::Missing;
};
if values.next().is_some() {
return Self::Multiple;
}
Self::from_value(value)
}
#[must_use]
pub(crate) const fn dataplane_error(self) -> Option<&'static str> {
match self {
Self::Dataplane => None,
Self::Missing => Some("dataplane response backend marker is missing"),
Self::ControlplaneFallback => {
Some("dataplane response backend marker identifies controlplane fallback")
}
Self::Controlplane => Some("dataplane response backend marker identifies controlplane"),
Self::Invalid => Some("dataplane response backend marker is invalid"),
Self::Multiple => Some("dataplane response backend marker is duplicated"),
}
}
fn from_value(value: &HeaderValue) -> Self {
match value.as_bytes() {
value if value == DATAPLANE_BACKEND.as_bytes() => Self::Dataplane,
value if value == CONTROLPLANE_FALLBACK_BACKEND.as_bytes() => {
Self::ControlplaneFallback
}
value if value == CONTROLPLANE_BACKEND.as_bytes() => Self::Controlplane,
_ => Self::Invalid,
}
}
}
#[must_use]
pub(crate) fn sanitized_backend_value(value: &HeaderValue) -> &'static str {
match BackendIdentity::from_value(value) {
BackendIdentity::Dataplane => DATAPLANE_BACKEND,
BackendIdentity::ControlplaneFallback => CONTROLPLANE_FALLBACK_BACKEND,
BackendIdentity::Controlplane => CONTROLPLANE_BACKEND,
BackendIdentity::Missing | BackendIdentity::Invalid | BackendIdentity::Multiple => {
"<invalid>"
}
}
}
#[must_use]
pub(crate) fn is_dataplane_endpoint(endpoint: &Url) -> bool {
let Some(mut segments) = endpoint.path_segments() else {
return false;
};
matches!(segments.next(), Some("servers"))
&& segments
.next()
.is_some_and(|server_id| !server_id.is_empty())
&& matches!(segments.next(), Some("mcp"))
&& segments.next().is_none()
}