use std::collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(deny_unknown_fields)]
#[schemars(example = override_subgraph_urls_example_1())]
pub struct OverrideSubgraphUrlsConfig {
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub subgraphs: HashMap<String, OverrideUrlConfig>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub all: Option<OverrideAllUrlConfig>,
}
impl OverrideSubgraphUrlsConfig {
pub fn get_subgraph_url(&self, subgraph_name: &str) -> Option<&UrlOrExpression> {
self.subgraphs.get(subgraph_name).map(|config| &config.url)
}
pub fn get_all_url(&self) -> Option<&str> {
self.all
.as_ref()
.map(|config| config.url.expression.as_str())
}
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(deny_unknown_fields)]
pub struct OverrideUrlConfig {
pub url: UrlOrExpression,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(deny_unknown_fields)]
pub struct OverrideAllUrlConfig {
pub url: OverrideExpressionConfig,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(deny_unknown_fields)]
pub struct OverrideExpressionConfig {
pub expression: String,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
#[serde(untagged)]
pub enum UrlOrExpression {
Url(String),
Expression { expression: String },
}
#[cfg(test)]
mod tests {
use crate::config::parse_yaml_config;
#[test]
fn rejects_static_all_url_override() {
let config = r#"
supergraph:
source: file
path: supergraph.graphql
override_subgraph_urls:
all:
url: "https://example.com/graphql"
"#;
let result = parse_yaml_config(config.to_string());
assert!(result.is_err(), "expected static all.url to be rejected");
}
}
fn override_subgraph_urls_example_1() -> OverrideSubgraphUrlsConfig {
let expression = r#"
if .request.headers."x-region" == "us-east" {
"https://products-us-east.example.com/graphql"
} else if .request.headers."x-region" == "eu-west" {
"https://products-eu-west.example.com/graphql"
} else {
.default
}
"#;
let mut subgraphs = HashMap::new();
subgraphs.insert(
"accounts".to_string(),
OverrideUrlConfig {
url: UrlOrExpression::Url("https://accounts.example.com/graphql".to_string()),
},
);
subgraphs.insert(
"products".to_string(),
OverrideUrlConfig {
url: UrlOrExpression::Expression {
expression: expression.to_string(),
},
},
);
OverrideSubgraphUrlsConfig {
subgraphs,
all: None,
}
}