aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGus Power <gus@infinitesidequests.com>2025-05-12 10:52:28 +0100
committerGus Power <gus@infinitesidequests.com>2025-05-12 10:52:28 +0100
commit1d6fd8359fddbae8aeac17b90ed50d41143ffbb6 (patch)
tree7872e1e112ea9ed440caecad9755da751de59ccd /src
parente1f43bb48b23338ce103dc92a53a13e72021299d (diff)
skeleton dyndns service, split into ip and dyndns modules
Diffstat (limited to 'src')
-rw-r--r--src/dyndns_service.rs67
-rw-r--r--src/ip_service.rs74
-rw-r--r--src/main.rs24
-rw-r--r--src/test.rs48
4 files changed, 143 insertions, 70 deletions
diff --git a/src/dyndns_service.rs b/src/dyndns_service.rs
new file mode 100644
index 0000000..caa163d
--- /dev/null
+++ b/src/dyndns_service.rs
@@ -0,0 +1,67 @@
+use reqwest::ClientBuilder;
+use std::error::Error;
+
+struct DynDnsService {}
+
+impl DynDnsService {
+ pub async fn register(config: &impl DynDnsServiceConfiguration) -> Result<(), Box<dyn Error>> {
+ let client = ClientBuilder::new().build()?;
+ client.post(config.get_service_url()).send().await?;
+ Ok(())
+ }
+}
+
+trait DynDnsServiceConfiguration {
+ fn get_service_url(&self) -> String;
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::error::Error;
+ use wiremock::matchers::{method, path};
+ use wiremock::{Mock, MockServer, ResponseTemplate};
+
+ async fn setup_dyndns_service(service_path: &str) -> MockServer {
+ let service = MockServer::start().await;
+
+ Mock::given(method("POST"))
+ .and(path(service_path))
+ .respond_with(ResponseTemplate::new(200))
+ .mount(&service)
+ .await;
+
+ service
+ }
+
+ #[tokio::test]
+ async fn successful_dyndns_registration() -> Result<(), Box<dyn Error>> {
+ let service_path = "register-my-ip-address";
+
+ let dyndns_service = setup_dyndns_service(service_path).await;
+ let service_config = TestDynDnsServiceConfiguration::new(&dyndns_service, service_path);
+
+ DynDnsService::register(&service_config).await?;
+ assert_eq!(1, dyndns_service.received_requests().await.unwrap().len());
+
+ Ok(())
+ }
+
+ struct TestDynDnsServiceConfiguration {
+ service_path: String,
+ }
+
+ impl TestDynDnsServiceConfiguration {
+ fn new(server: &MockServer, path: &str) -> Self {
+ Self {
+ service_path: format!("{}/{}", server.uri(), path),
+ }
+ }
+ }
+
+ impl DynDnsServiceConfiguration for TestDynDnsServiceConfiguration {
+ fn get_service_url(&self) -> String {
+ self.service_path.clone()
+ }
+ }
+}
diff --git a/src/ip_service.rs b/src/ip_service.rs
new file mode 100644
index 0000000..8e2bee8
--- /dev/null
+++ b/src/ip_service.rs
@@ -0,0 +1,74 @@
+use reqwest::Url;
+use std::error::Error;
+use std::net::IpAddr;
+use std::str::FromStr;
+
+pub struct IpService {}
+
+impl IpService {
+ async fn resolve(config: &impl IpServiceConfiguration) -> Result<IpAddr, Box<dyn Error>> {
+ let response = reqwest::get(config.get_service_url()).await.unwrap();
+ Ok(IpAddr::from_str(&response.text().await.unwrap())?)
+ }
+}
+
+pub trait IpServiceConfiguration {
+ fn get_service_url(&self) -> Url;
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::net::Ipv4Addr;
+ use wiremock::matchers::{method, path};
+ use wiremock::{Mock, MockServer, ResponseTemplate};
+
+ async fn setup_ipv4_service(service_path: &str, response: &str) -> MockServer {
+ let service = MockServer::start().await;
+
+ Mock::given(method("GET"))
+ .and(path(service_path))
+ .respond_with(
+ ResponseTemplate::new(200)
+ .insert_header("Content-Type", "text/plain; charset=utf-8")
+ .set_body_string(response),
+ )
+ .mount(&service)
+ .await;
+
+ service
+ }
+
+ #[tokio::test]
+ async fn successful_ipv4_address_resolution() -> Result<(), Box<dyn Error>> {
+ let service_path = "get-my-ip-address";
+ let service_response = "17.5.7.8";
+
+ let ip_service = setup_ipv4_service(service_path, service_response).await;
+ let service_config = MockConfig::new(&ip_service, service_path);
+
+ let actual = IpService::resolve(&service_config).await?;
+ assert_eq!(actual, IpAddr::V4(Ipv4Addr::new(17, 5, 7, 8)));
+
+ assert_eq!(1, ip_service.received_requests().await.unwrap().len());
+
+ Ok(())
+ }
+
+ struct MockConfig {
+ service_url: Url,
+ }
+
+ impl MockConfig {
+ fn new(server: &MockServer, path: &str) -> Self {
+ Self {
+ service_url: Url::parse(format!("{}/{}", server.uri(), path).as_str()).unwrap(),
+ }
+ }
+ }
+ impl IpServiceConfiguration for MockConfig {
+ fn get_service_url(&self) -> Url {
+ self.service_url.clone()
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 428ebf9..1ae22b8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,26 +1,6 @@
-use std::error::Error;
-use std::net::IpAddr;
-use std::str::FromStr;
-use reqwest::Url;
-
-#[cfg(test)]
-mod test;
+mod dyndns_service;
+mod ip_service;
fn main() {
println!("Hello, world!");
}
-
-pub struct IpService {}
-
-impl IpService {
-
- async fn resolve(config: &impl IpServiceConfiguration) -> Result<IpAddr, Box<dyn Error>> {
- let response = reqwest::get(config.get_service_url()).await.unwrap();
- Ok(IpAddr::from_str(&response.text().await.unwrap())?)
- }
-
-}
-
-pub trait IpServiceConfiguration {
- fn get_service_url(&self) -> Url;
-}
diff --git a/src/test.rs b/src/test.rs
deleted file mode 100644
index f2c4219..0000000
--- a/src/test.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use std::net::{IpAddr, Ipv4Addr};
-use reqwest::Url;
-use wiremock::{Mock, MockServer, ResponseTemplate};
-use wiremock::matchers::{method, path};
-use crate::{IpService, IpServiceConfiguration};
-
-async fn setup_ipv4_service(service_path: &str, response: &str) -> MockServer {
- let ip_service = MockServer::start().await;
-
- Mock::given(method("GET"))
- .and(path(service_path))
- .respond_with(ResponseTemplate::new(200)
- .insert_header("Content-Type", "text/plain; charset=utf-8")
- .set_body_string(response))
- .mount(&ip_service)
- .await;
-
- ip_service
-}
-
-#[tokio::test]
-async fn successful_ipv4_address_resolution() {
- let service_path = "get-my-ip-address";
- let service_response = "17.5.7.8";
-
- let ip_service = setup_ipv4_service(service_path, service_response).await;
- let service_config = TestIpServiceConfiguration::new(&ip_service, service_path);
-
- let actual = IpService::resolve(&service_config).await.unwrap();
- assert_eq!(actual, IpAddr::V4(Ipv4Addr::new(17, 5, 7, 8)))
-}
-
-struct TestIpServiceConfiguration {
- service_url: Url,
-}
-
-impl TestIpServiceConfiguration {
- fn new(server: &MockServer, path: &str) -> Self {
- Self {
- service_url: Url::parse(format!("{}/{}", server.uri(), path).as_str()).unwrap()
- }
- }
-}
-impl IpServiceConfiguration for TestIpServiceConfiguration {
- fn get_service_url(&self) -> Url {
- self.service_url.clone()
- }
-}