adding optional query parameters

This commit is contained in:
Johannes Theiner 2020-07-21 16:50:51 +02:00
parent 08da856351
commit 4761167e1c
5 changed files with 76 additions and 15 deletions

View File

@ -9,22 +9,23 @@ import (
"strconv" "strconv"
) )
func GetByCityName(city string) WeatherResponse { var baseUrl = "https://api.openweathermap.org/data/2.5/weather"
return get("https://api.openweathermap.org/data/2.5/weather?q=" + city)
func GetByCityName(city string, language string, unit config.Units) WeatherResponse {
return get(baseUrl+"?q="+city, language, unit)
} }
func GetByCoordinates(longitude, latitude float64) WeatherResponse { func GetByCoordinates(longitude, latitude float64, language string, unit config.Units) WeatherResponse {
return get("https://api.openweathermap.org/data/2.5/weather?lat=" + strconv.FormatFloat(latitude, 'f', 6, 32) + "&lon=" + strconv.FormatFloat(longitude, 'f', 6, 32)) return get(baseUrl+"?lat="+strconv.FormatFloat(latitude, 'f', 6, 32)+"&lon="+strconv.FormatFloat(longitude, 'f', 6, 32), language, unit)
} }
func GetByZipCode(zip int, country string) WeatherResponse { func GetByZipCode(zip int, country string, language string, unit config.Units) WeatherResponse {
return get("https://api.openweathermap.org/data/2.5/weather?zip=" + string(zip) + "," + country) return get(baseUrl+"?zip="+string(zip)+","+country, language, unit)
} }
func get(url string, language string, unit config.Units) WeatherResponse {
func get(url string) WeatherResponse {
var configuration = config.LoadConfiguration() var configuration = config.LoadConfiguration()
response, err := http.Get(url + "&appid=" + configuration.ApiKey + "&lang=" + configuration.Language + "&units=" + configuration.Units) response, err := http.Get(url + "&appid=" + configuration.ApiKey + "&lang=" + language + "&units=" + unit.String())
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -2,6 +2,7 @@ package client
type WeatherResponse struct { type WeatherResponse struct {
Coordinates Coordinates `json:"coord,omitempty"` Coordinates Coordinates `json:"coord,omitempty"`
Weather []Weather `json:"weather,omitempty"`
Base string `json:"base,omitempty"` Base string `json:"base,omitempty"`
Main Main `json:"main,omitempty"` Main Main `json:"main,omitempty"`
Visibility int `json:"visibility,omitempty"` Visibility int `json:"visibility,omitempty"`
@ -17,6 +18,13 @@ type WeatherResponse struct {
Cod int `json:"cod,omitempty"` Cod int `json:"cod,omitempty"`
} }
type Weather struct {
Id int `json:"id,omitempty"`
Main string `json:"main,omitempty"`
Description string `json:"description,omitempty"`
Icon string `json:"icon,omitempty"`
}
type Coordinates struct { type Coordinates struct {
Longitude float32 `json:"lon,omitempty"` Longitude float32 `json:"lon,omitempty"`
Latitude float32 `json:"lat,omitempty"` Latitude float32 `json:"lat,omitempty"`

View File

@ -4,12 +4,13 @@ import (
"fmt" "fmt"
"os" "os"
"strconv" "strconv"
"strings"
) )
type Configuration struct { type Configuration struct {
ApiKey string ApiKey string
Language string Language string
Units string Units Units
Port int Port int
JwtSecret string JwtSecret string
@ -26,7 +27,7 @@ func LoadConfiguration() *Configuration {
return &Configuration{ return &Configuration{
ApiKey: getEnv("API_KEY", ""), ApiKey: getEnv("API_KEY", ""),
Language: getEnv("LANGUAGE", "en"), Language: getEnv("LANGUAGE", "en"),
Units: getEnv("UNITS", "metric"), Units: StringToUnit(getEnv("UNITS", "metric")),
Port: getEnvAsInt("PORT", 8080), Port: getEnvAsInt("PORT", 8080),
JwtSecret: getEnv("JWT_SECRET", "super secret value"), JwtSecret: getEnv("JWT_SECRET", "super secret value"),
SentryDsn: getEnv("SENTRY_DSN", ""), SentryDsn: getEnv("SENTRY_DSN", ""),
@ -51,3 +52,23 @@ func getEnvAsInt(name string, defaultVal int) int {
return defaultVal return defaultVal
} }
type Units int
const (
Metric Units = iota
Imperial
)
func (unit Units) String() string {
return [...]string{"metric", "imperial"}[unit]
}
func StringToUnit(string string) Units {
if strings.EqualFold(string, "metric") {
return Metric
} else {
return Imperial
}
}

View File

@ -20,8 +20,10 @@ import (
"time" "time"
) )
var conf *config.Configuration
func StartServer() { func StartServer() {
conf := config.LoadConfiguration() conf = config.LoadConfiguration()
port := strconv.Itoa(conf.Port) port := strconv.Itoa(conf.Port)
log.Println("starting server on port " + port) log.Println("starting server on port " + port)
@ -97,7 +99,16 @@ func defaultHandler(writer http.ResponseWriter, _ *http.Request) {
func cityHandler(writer http.ResponseWriter, req *http.Request) { func cityHandler(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json") writer.Header().Set("Content-Type", "application/json")
vars := mux.Vars(req) vars := mux.Vars(req)
data := client.GetByCityName(vars["city"])
if vars["city"] == "" {
if _, err := writer.Write([]byte("no city provided")); err != nil {
panic(err)
}
}
language, units := getOptionalArgs(req)
data := client.GetByCityName(vars["city"], language, units)
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
if err := json.NewEncoder(writer).Encode(convert(data)); err != nil { if err := json.NewEncoder(writer).Encode(convert(data)); err != nil {
panic(err) panic(err)
@ -116,7 +127,9 @@ func coordinatesHandler(writer http.ResponseWriter, req *http.Request) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
data := client.GetByCoordinates(longitude, latitude) language, units := getOptionalArgs(req)
data := client.GetByCoordinates(longitude, latitude, language, units)
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
if err := json.NewEncoder(writer).Encode(convert(data)); err != nil { if err := json.NewEncoder(writer).Encode(convert(data)); err != nil {
panic(err) panic(err)
@ -130,7 +143,7 @@ func zipCodeHandler(writer http.ResponseWriter, req *http.Request) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
data := client.GetByZipCode(zip, vars["country"]) data := client.GetByZipCode(zip, vars["country"], config.LoadConfiguration().Language, config.Metric)
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
if err := json.NewEncoder(writer).Encode(convert(data)); err != nil { if err := json.NewEncoder(writer).Encode(convert(data)); err != nil {
panic(err) panic(err)
@ -141,6 +154,20 @@ func timeoutHandler(h http.Handler) http.Handler {
return http.TimeoutHandler(h, 1*time.Second, "timed out") return http.TimeoutHandler(h, 1*time.Second, "timed out")
} }
func getOptionalArgs(req *http.Request) (language string, units config.Units) {
language = conf.Language
units = conf.Units
if lang := req.URL.Query().Get("language"); lang != "" {
language = lang
}
if unit := req.URL.Query().Get("units"); unit != "" {
units = config.StringToUnit(unit)
}
return language, units
}
func convert(weatherData client.WeatherResponse) Weather { func convert(weatherData client.WeatherResponse) Weather {
return Weather{ return Weather{
TemperatureCurrent: weatherData.Main.Temperature, TemperatureCurrent: weatherData.Main.Temperature,
@ -149,6 +176,8 @@ func convert(weatherData client.WeatherResponse) Weather {
FeelsLike: weatherData.Main.FeelsLike, FeelsLike: weatherData.Main.FeelsLike,
Pressure: weatherData.Main.Pressure, Pressure: weatherData.Main.Pressure,
Humidity: weatherData.Main.Humidity, Humidity: weatherData.Main.Humidity,
Description: weatherData.Weather[0].Description,
Icon: weatherData.Weather[0].Icon,
WindSpeeed: weatherData.Wind.Speed, WindSpeeed: weatherData.Wind.Speed,
WindDegree: weatherData.Wind.Degree, WindDegree: weatherData.Wind.Degree,
Clouds: weatherData.Clouds.All, Clouds: weatherData.Clouds.All,

View File

@ -7,6 +7,8 @@ type Weather struct {
TemperatureMax float32 `json:"temperature_max"` TemperatureMax float32 `json:"temperature_max"`
Pressure int `json:"pressure"` Pressure int `json:"pressure"`
Humidity int `json:"humidity"` Humidity int `json:"humidity"`
Description string `json:"description"`
Icon string `json:"icon"`
WindSpeeed float32 `json:"wind_speed"` WindSpeeed float32 `json:"wind_speed"`
WindDegree int `json:"wind_degree"` WindDegree int `json:"wind_degree"`