Basic endpoint to get weather for a location

This commit is contained in:
Rob Watson 2020-10-16 17:12:14 +02:00
parent 87bdaede13
commit bcdc7c7e01
5 changed files with 1757 additions and 2 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target
.env

1663
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,3 +7,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dotenv = "0.15.0"
reqwest = { version = "0.10.8", features = ["json"] }
rocket = { git = "https://github.com/SergioBenitez/Rocket", default-features = false }
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket" }
serde = { version = "1.0", features = ["derive"] }

View File

@ -1,3 +1,19 @@
fn main() {
println!("Hello, world!");
#[macro_use]
extern crate rocket;
use dotenv::dotenv;
mod weather;
#[get("/weather/<loc>")]
async fn get_weather(loc: String) -> Result<String, String> {
let sum = weather::get_summary(&loc).await?;
Ok(format!("The weather in {} is: {:?}", loc, sum))
}
#[rocket::launch]
fn rocket() -> rocket::Rocket {
dotenv().ok();
rocket::ignite().mount("/", routes![get_weather])
}

70
src/weather.rs Normal file
View File

@ -0,0 +1,70 @@
use crate::rocket::futures::TryFutureExt;
use serde::Deserialize;
use std::env;
#[derive(Debug, Deserialize)]
struct APIResponseWeather {
main: String,
description: String,
}
#[derive(Debug, Deserialize)]
struct APIResponseMain {
temp: f32,
feels_like: f32,
humidity: u32,
pressure: u32,
}
#[derive(Debug, Deserialize)]
struct APIResponse {
weather: Vec<APIResponseWeather>,
main: APIResponseMain,
}
#[derive(Debug)]
pub enum WeatherSummary {
Clear(i32),
Drizzle(i32),
Rain(i32),
Snow(i32),
Cloudy(i32),
Thunderstorm(i32),
Other(i32, String),
}
impl From<APIResponse> for WeatherSummary {
fn from(resp: APIResponse) -> Self {
let temp = resp.main.temp as i32;
match resp.weather[0].main.as_ref() {
"Thunderstorm" => Self::Thunderstorm(temp),
"Drizzle" => Self::Drizzle(temp),
"Rain" => Self::Rain(temp),
"Snow" => Self::Snow(temp),
"Clear" => Self::Clear(temp),
"Clouds" => Self::Cloudy(temp),
_ => Self::Other(temp, resp.weather[0].description.clone()),
}
}
}
pub async fn get_summary(loc: &str) -> Result<WeatherSummary, String> {
let api_key =
env::var("OPEN_WEATHERMAP_API_KEY").expect("could not load OPEN_WEATHERMAP_API_KEY");
let url = format!(
"https://api.openweathermap.org/data/2.5/weather?q={}&appid={}&units=metric",
loc, api_key
);
println!("Got URL: {}", &url);
let body = reqwest::get(&url)
.map_err(|e| e.to_string())
.await?
.json::<APIResponse>()
.map_err(|e| e.to_string())
.await?;
Ok(body.into())
}