smbcloud_network/
network.rs

1use log::{debug, error};
2use reqwest::{RequestBuilder, Response};
3use serde::de::DeserializeOwned;
4use smbcloud_model::error_codes::{ErrorCode, ErrorResponse};
5//use std::time::Duration;
6#[cfg(debug_assertions)]
7const LOG_RESPONSE_BODY: bool = false; // You know what to do here.
8#[cfg(not(debug_assertions))]
9const LOG_RESPONSE_BODY: bool = false;
10
11/// Check if there is an active internet connection
12///
13/// This function attempts to connect to a reliable server (dns.google)
14/// with a short timeout. Returns true if the connection was successful.
15pub async fn check_internet_connection() -> bool {
16    debug!("Checking internet connection");
17    let client = reqwest::Client::builder()
18        //.timeout(Duration::from_secs(5)) Does not work on wasm32
19        .build();
20
21    if let Err(e) = client {
22        error!("Failed to create client for connectivity check: {:?}", e);
23        return false;
24    }
25
26    if let Ok(client) = client {
27        match client.get("https://dns.google").send().await {
28            Ok(response) => {
29                debug!(
30                    "Internet connection check successful: {}",
31                    response.status()
32                );
33                response.status().is_success()
34            }
35            Err(e) => {
36                error!("Internet connection check failed: {:?}", e);
37                false
38            }
39        }
40    } else {
41        false
42    }
43}
44
45pub async fn parse_error_response<T: DeserializeOwned>(
46    response: Response,
47) -> Result<T, ErrorResponse> {
48    let response_body = match response.text().await {
49        Ok(body) => body,
50        Err(e) => {
51            error!("Failed to get response body: {:?}", e);
52            return Err(ErrorResponse::Error {
53                error_code: ErrorCode::NetworkError,
54                message: ErrorCode::NetworkError.message(None).to_string(),
55            });
56        }
57    };
58
59    if LOG_RESPONSE_BODY {
60        println!();
61        println!("Parse Error >>>>");
62        println!("{:?}", serde_json::to_string_pretty(&response_body));
63        println!("Parse Error >>>>");
64        println!();
65    }
66
67    let e = match serde_json::from_str::<ErrorResponse>(&response_body) {
68        Ok(json) => json,
69        Err(e) => {
70            error!("Failed to parse error response: {:?}", e);
71            return Err(ErrorResponse::Error {
72                error_code: ErrorCode::ParseError,
73                message: ErrorCode::ParseError.message(None).to_string(),
74            });
75        }
76    };
77    error!("Error response: {:?}", e);
78    Err(e)
79}
80
81pub async fn request<R: DeserializeOwned>(builder: RequestBuilder) -> Result<R, ErrorResponse> {
82    // Check internet connection before making the request
83    if !check_internet_connection().await {
84        error!("No internet connection available");
85        return Err(ErrorResponse::Error {
86            error_code: ErrorCode::NetworkError,
87            message: "No internet connection. Please check your network settings and try again."
88                .to_string(),
89        });
90    }
91
92    let response = builder.send().await;
93    let response = match response {
94        Ok(response) => response,
95        Err(e) => {
96            error!("Failed to get response: {:?}", e);
97            return Err(ErrorResponse::Error {
98                error_code: ErrorCode::NetworkError,
99                message: ErrorCode::NetworkError.message(None).to_string(),
100            });
101        }
102    };
103    let response = match response.status() {
104        reqwest::StatusCode::OK | reqwest::StatusCode::CREATED => response,
105        status => {
106            error!("Failed to get response: {:?}", status);
107            return parse_error_response(response).await;
108        }
109    };
110
111    let response_body = match response.text().await {
112        Ok(body) => body,
113        Err(e) => {
114            error!("Failed to get response body: {:?}", e);
115            return Err(ErrorResponse::Error {
116                error_code: ErrorCode::NetworkError,
117                message: ErrorCode::NetworkError.message(None).to_string(),
118            });
119        }
120    };
121
122    if LOG_RESPONSE_BODY {
123        println!();
124        println!("Parse >>>>");
125        println!("{:?}", serde_json::to_string_pretty(&response_body));
126        println!("Parse >>>>");
127        println!();
128    }
129
130    let response = match serde_json::from_str::<R>(&response_body) {
131        Ok(response) => response,
132        Err(e) => {
133            error!("Failed to parse response: {:?}", e);
134            return Err(ErrorResponse::Error {
135                error_code: ErrorCode::ParseError,
136                message: e.to_string(),
137            });
138        }
139    };
140
141    Ok(response)
142}