-
Notifications
You must be signed in to change notification settings - Fork 245
/
override_url.rs
126 lines (110 loc) 路 3.48 KB
/
override_url.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! Allows subgraph URLs to be overridden.
use std::collections::HashMap;
use std::str::FromStr;
use http::Uri;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use tower::BoxError;
use tower::ServiceExt;
use crate::plugin::Plugin;
use crate::plugin::PluginInit;
use crate::register_plugin;
use crate::services::subgraph;
use crate::services::SubgraphRequest;
#[derive(Debug, Clone)]
struct OverrideSubgraphUrl {
urls: HashMap<String, Uri>,
}
/// Subgraph URL mappings
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[serde(untagged)]
enum Conf {
/// Subgraph URL mappings
Mapping(HashMap<String, url::Url>),
}
#[async_trait::async_trait]
impl Plugin for OverrideSubgraphUrl {
type Config = Conf;
async fn new(init: PluginInit<Self::Config>) -> Result<Self, BoxError> {
let Conf::Mapping(urls) = init.config;
Ok(OverrideSubgraphUrl {
urls: urls
.into_iter()
.map(|(k, v)| (k, Uri::from_str(v.as_str()).unwrap()))
.collect(),
})
}
fn subgraph_service(
&self,
subgraph_name: &str,
service: subgraph::BoxService,
) -> subgraph::BoxService {
let new_url = self.urls.get(subgraph_name).cloned();
service
.map_request(move |mut req: SubgraphRequest| {
if let Some(new_url) = new_url.clone() {
*req.subgraph_request.uri_mut() = new_url;
}
req
})
.boxed()
}
}
register_plugin!("apollo", "override_subgraph_url", OverrideSubgraphUrl);
#[cfg(test)]
mod tests {
use std::str::FromStr;
use http::Uri;
use serde_json::Value;
use tower::util::BoxService;
use tower::Service;
use tower::ServiceExt;
use crate::plugin::test::MockSubgraphService;
use crate::plugin::DynPlugin;
use crate::services::SubgraphRequest;
use crate::services::SubgraphResponse;
use crate::Context;
#[tokio::test]
async fn plugin_registered() {
let mut mock_service = MockSubgraphService::new();
mock_service
.expect_call()
.withf(|req| {
req.subgraph_request.uri() == &Uri::from_str("http://localhost:8001").unwrap()
})
.times(1)
.returning(move |req: SubgraphRequest| {
Ok(SubgraphResponse::fake_builder()
.context(req.context)
.build())
});
let dyn_plugin: Box<dyn DynPlugin> = crate::plugin::plugins()
.find(|factory| factory.name == "apollo.override_subgraph_url")
.expect("Plugin not found")
.create_instance_without_schema(
&Value::from_str(
r#"{
"test_one": "http://localhost:8001",
"test_two": "http://localhost:8002"
}"#,
)
.unwrap(),
)
.await
.unwrap();
let mut subgraph_service =
dyn_plugin.subgraph_service("test_one", BoxService::new(mock_service));
let context = Context::new();
context.insert("test".to_string(), 5i64).unwrap();
let subgraph_req = SubgraphRequest::fake_builder().context(context);
let _subgraph_resp = subgraph_service
.ready()
.await
.unwrap()
.call(subgraph_req.build())
.await
.unwrap();
}
}