Technical test for a job interview.
1extern crate reqwest;
2
3use std::time::Duration;
4// use serde_json::Value;
5use crate::utils;
6
7/// Returns our own Http Client with a 10 sec timeout
8pub fn create_client() -> Option<reqwest::blocking::Client> {
9 reqwest::blocking::Client::builder().timeout(Duration::from_secs(10)).build().ok()
10}
11
12/// Returns the default API call by city name with optional arguments concatenated into a String
13fn concat_url(api_id: String,
14 query: utils::Query,
15 city_name: String,
16 state_code: Option<String>,
17 country_code: Option<String>,
18 unit: utils::Temp) -> String
19{
20 // Patern matching the query type
21 let query_type = match query
22 {
23 utils::Query::Weather => String::from("weather"), // Get current weather
24 utils::Query::Forecast => String::from("forecast"), // Get forecast
25 };
26
27 // Patern matching the state code
28 let state_str = match state_code
29 {
30 None => String::new(), // Get an empty string if there's None
31 Some(s) => format!(",{}", s) // Prefix a comma if there's Some
32 };
33
34 // Patern matching the country code
35 let country_str = match country_code
36 {
37 None => String::new(), // Get an empty string if there's None
38 Some(s) => format!(",{}", s) // Prefix a comma if there's Some
39 };
40
41 let temp_unit = match unit
42 {
43 utils::Temp::K => String::new(),
44 utils::Temp::C => String::from("&units=metric"),
45 utils::Temp::F => String::from("&units=imperial"),
46 };
47
48 format!("http://api.openweathermap.org/data/2.5/{}?q={}{}{}&appid={}{}",
49 &query_type,
50 &city_name,
51 &state_str,
52 &country_str,
53 &api_id,
54 &temp_unit
55 )
56}
57
58/// Performs the API call and returns the JSON
59pub fn call_api(client: Option<reqwest::blocking::Client>,
60 query_type: utils::Query,
61 api_id: String,
62 city_name: String,
63 state_code: Option<String>,
64 country_code: Option<String>,
65 temp_unit: utils::Temp) -> Option<String>
66{
67 // Patern matching the client argument
68 let my_client = match client
69 {
70 None => { // if it's None, create a new one
71 match create_client()
72 {
73 Some(c) => c,
74 None => panic!("Couldn't create Http Client"),
75 }
76 },
77 Some(c) => c, // If it already has Some value, unwrap it
78 };
79
80 let url = concat_url(api_id, query_type, city_name, state_code, country_code, temp_unit);
81 let url = reqwest::Url::parse(&url).unwrap();
82 let req = my_client.get(url).send();
83
84 // Patern matching the request result
85 match req
86 {
87 Err(_) => panic!("Couldn't get a response"),
88 Ok(res) => {
89 if let Ok(val) = res.text() // If there is a body
90 {
91 if !val.is_empty()
92 {
93 Some(val)
94 }
95 else
96 {
97 println!("Got an empty response body");
98 None
99 }
100 }
101 else
102 {
103 println!("Got an empty/unparseable response");
104 None
105 }
106 },
107 }
108}