reactive_graph_remotes_model/
instance_address.rs

1use serde::Deserialize;
2use serde::Serialize;
3use std::hash::Hash;
4use std::hash::Hasher;
5use typed_builder::TypedBuilder;
6
7pub const DEFAULT_HOSTNAME: &str = "localhost";
8pub const DEFAULT_PORT: u16 = 31415;
9pub const DEFAULT_USER_AGENT: &str = "reactive_graph_client";
10pub const DEFAULT_ENDPOINT_GRAPHQL: &str = "/graphql";
11pub const DEFAULT_ENDPOINT_DYNAMIC_GRAPH: &str = "/dynamic_graph";
12pub const DEFAULT_ENDPOINT_RUNTIME: &str = "/runtime/graphql";
13pub const DEFAULT_ENDPOINT_PLUGIN: &str = "/plugin/graphql";
14
15#[derive(Clone, Debug, Eq, Deserialize, Serialize, TypedBuilder)]
16#[serde(rename_all = "camelCase")]
17pub struct InstanceAddress {
18    /// The hostname of the GraphQL server.
19    #[builder(default = DEFAULT_HOSTNAME.to_owned())]
20    pub hostname: String,
21
22    /// The port of the GraphQL server.
23    #[builder(default = DEFAULT_PORT)]
24    #[serde(default = "default_port", skip_serializing_if = "is_default_port")]
25    pub port: u16,
26
27    /// If true, HTTPS will be used.
28    #[builder(default = false)]
29    #[serde(default = "bool::default", skip_serializing_if = "is_default")]
30    pub secure: bool,
31
32    /// The user agent.
33    #[builder(default = DEFAULT_USER_AGENT.to_owned())]
34    #[serde(default = "default_user_agent", skip_serializing_if = "is_default_user_agent")]
35    pub user_agent: String,
36
37    /// The relative URL of the GraphQL endpoint, by default "/graphql".
38    #[builder(default = DEFAULT_ENDPOINT_GRAPHQL.to_owned())]
39    #[serde(default = "default_endpoint_graphql", skip_serializing_if = "is_default_endpoint_graphql")]
40    pub endpoint_graphql: String,
41
42    /// The relative URL of the GraphQL endpoint, by default "/graphql".
43    #[builder(default = DEFAULT_ENDPOINT_DYNAMIC_GRAPH.to_owned())]
44    #[serde(default = "default_endpoint_dynamic_graph", skip_serializing_if = "is_default_endpoint_dynamic_graph")]
45    pub endpoint_dynamic_graph: String,
46
47    /// The relative URL of the GraphQL endpoint, by default "/graphql".
48    #[builder(default = DEFAULT_ENDPOINT_RUNTIME.to_owned())]
49    #[serde(default = "default_endpoint_runtime", skip_serializing_if = "is_default_endpoint_runtime")]
50    pub endpoint_runtime: String,
51
52    /// The relative URL of the GraphQL endpoint, by default "/graphql".
53    #[builder(default = DEFAULT_ENDPOINT_PLUGIN.to_owned())]
54    #[serde(default = "default_endpoint_plugin", skip_serializing_if = "is_default_endpoint_plugin")]
55    pub endpoint_plugin: String,
56
57    /// The authentication token.
58    #[builder(default)]
59    pub bearer: Option<String>,
60
61    /// Controls the use of certificate validation.
62    ///
63    /// Defaults to `false`.
64    ///
65    /// Warning: You should think very carefully before using this method. If
66    /// invalid certificates are trusted, *any* certificate for *any* site
67    /// will be trusted for use. This includes expired certificates. This
68    /// introduces significant vulnerabilities, and should only be used
69    /// as a last resort.
70    #[builder(default)]
71    pub danger_accept_invalid_certs: Option<bool>,
72
73    /// Controls the use of hostname verification.
74    ///
75    /// Defaults to `false`.
76    ///
77    /// Warning: You should think very carefully before you use this method. If
78    /// hostname verification is not used, any valid certificate for any
79    /// site will be trusted for use from any other. This introduces a
80    /// significant vulnerability to man-in-the-middle attacks.
81    #[builder(default)]
82    pub danger_accept_invalid_hostnames: Option<bool>,
83}
84
85impl InstanceAddress {
86    pub fn new(hostname: String, port: u16, secure: bool) -> InstanceAddress {
87        InstanceAddress {
88            hostname,
89            port,
90            secure,
91            user_agent: DEFAULT_USER_AGENT.to_string(),
92            endpoint_graphql: DEFAULT_ENDPOINT_GRAPHQL.to_string(),
93            endpoint_dynamic_graph: DEFAULT_ENDPOINT_DYNAMIC_GRAPH.to_string(),
94            endpoint_runtime: DEFAULT_ENDPOINT_RUNTIME.to_string(),
95            endpoint_plugin: DEFAULT_ENDPOINT_PLUGIN.to_string(),
96            bearer: None,
97            danger_accept_invalid_certs: None,
98            danger_accept_invalid_hostnames: None,
99        }
100    }
101
102    pub fn protocol(&self) -> String {
103        if self.secure { "https".to_string() } else { "http".to_string() }
104    }
105
106    pub fn base_url(&self) -> String {
107        format!("{}://{}:{}", self.protocol(), self.hostname, self.port)
108    }
109
110    pub fn url_reactive_graph(&self) -> String {
111        format!("{}{}", self.base_url(), self.endpoint_graphql)
112    }
113
114    pub fn url_dynamic_graph(&self) -> String {
115        format!("{}{}", self.base_url(), self.endpoint_dynamic_graph)
116    }
117
118    pub fn url_reactive_graph_runtime(&self) -> String {
119        format!("{}{}", self.base_url(), self.endpoint_runtime)
120    }
121
122    pub fn url_reactive_graph_plugins(&self) -> String {
123        format!("{}{}", self.base_url(), self.endpoint_plugin)
124    }
125}
126
127// An InstanceAddress is equals if hostname, port and secure are equal
128impl PartialEq<InstanceAddress> for InstanceAddress {
129    fn eq(&self, other: &InstanceAddress) -> bool {
130        self.hostname == other.hostname && self.port == other.port && self.secure == other.secure
131    }
132}
133
134impl Hash for InstanceAddress {
135    fn hash<H: Hasher>(&self, state: &mut H) {
136        self.hostname.hash(state);
137        self.port.hash(state);
138        self.secure.hash(state);
139    }
140}
141
142impl Default for InstanceAddress {
143    fn default() -> Self {
144        InstanceAddress {
145            hostname: DEFAULT_HOSTNAME.to_string(),
146            port: DEFAULT_PORT,
147            secure: false,
148            user_agent: DEFAULT_USER_AGENT.to_string(),
149            endpoint_graphql: DEFAULT_ENDPOINT_GRAPHQL.to_string(),
150            endpoint_dynamic_graph: DEFAULT_ENDPOINT_DYNAMIC_GRAPH.to_string(),
151            endpoint_runtime: DEFAULT_ENDPOINT_RUNTIME.to_string(),
152            endpoint_plugin: DEFAULT_ENDPOINT_PLUGIN.to_string(),
153            bearer: None,
154            danger_accept_invalid_certs: None,
155            danger_accept_invalid_hostnames: None,
156        }
157    }
158}
159
160fn default_port() -> u16 {
161    DEFAULT_PORT
162}
163
164fn is_default_port(port: &u16) -> bool {
165    DEFAULT_PORT == *port
166}
167
168fn default_user_agent() -> String {
169    DEFAULT_USER_AGENT.to_owned()
170}
171
172fn is_default_user_agent(user_agent: &String) -> bool {
173    DEFAULT_USER_AGENT == user_agent
174}
175
176fn default_endpoint_graphql() -> String {
177    DEFAULT_ENDPOINT_GRAPHQL.to_owned()
178}
179
180fn is_default_endpoint_graphql(endpoint: &String) -> bool {
181    DEFAULT_ENDPOINT_GRAPHQL == endpoint
182}
183
184fn default_endpoint_dynamic_graph() -> String {
185    DEFAULT_ENDPOINT_DYNAMIC_GRAPH.to_owned()
186}
187
188fn is_default_endpoint_dynamic_graph(endpoint: &String) -> bool {
189    DEFAULT_ENDPOINT_DYNAMIC_GRAPH == endpoint
190}
191
192fn default_endpoint_runtime() -> String {
193    DEFAULT_ENDPOINT_RUNTIME.to_owned()
194}
195
196fn is_default_endpoint_runtime(endpoint: &String) -> bool {
197    DEFAULT_ENDPOINT_RUNTIME == endpoint
198}
199
200fn default_endpoint_plugin() -> String {
201    DEFAULT_ENDPOINT_PLUGIN.to_owned()
202}
203
204fn is_default_endpoint_plugin(endpoint: &String) -> bool {
205    DEFAULT_ENDPOINT_PLUGIN == endpoint
206}
207
208fn is_default<T: Default + PartialEq>(t: &T) -> bool {
209    t == &T::default()
210}