Skip to content

Commit 450dee4

Browse files
Merge pull request #5 from kashifkhan0771/feature/history-api
Added history API
2 parents 09bade5 + cf21a73 commit 450dee4

File tree

6 files changed

+86
-16
lines changed

6 files changed

+86
-16
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ go get "github.com/kashifkhan0771/go-weather"
1818
)
1919

2020
func main() {
21-
config := weatherClient.WeatherAPIConfig{
22-
XApiKey: "<your_x_api_key>",
21+
config, err := weatherClient.NewWeatherAPIConfig(<Your_API_Key>)
22+
if err != nil {
23+
panic(err)
2324
}
2425

2526
weather, err := config.GetCurrentWeather(weatherClient.Options{Query: "Paris"})

config/configuration.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const (
66

77
// API EndPoints
88
CurrentWeatherJSON = "/current.json"
9+
HistoryWeatherJSON = "/history.json"
910

1011
// APIsTimeout is a timeout for all the API request to api.weatherapi.com
1112
APIsTimeout = 30

helper.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package go_weather
2+
3+
import (
4+
"time"
5+
)
6+
7+
// Define the minimum allowed date (2010-01-01)
8+
var minAllowedDate = time.Date(2010, 1, 1, 0, 0, 0, 0, time.UTC)
9+
10+
// validateQuery ensure the required query in the option is not empty
11+
func validateQuery(q string) bool {
12+
return q != ""
13+
}
14+
15+
// Ensure the date is on or after January 1st, 2010
16+
func validateDate(date time.Time) bool {
17+
if date.IsZero() {
18+
return false
19+
}
20+
21+
// Check if the input date is on or after 2010-01-01
22+
return !date.Before(minAllowedDate)
23+
}

options.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package go_weather
22

3+
import "time"
4+
35
/*
46
Options represent the query parameters of the APIs.
57
@@ -8,4 +10,6 @@ For more details about each query parameters, please visit: https://www.weathera
810
type Options struct {
911
// Query parameter based on which data is sent back (Required)
1012
Query string `json:"q"`
13+
// Date is required for history and future API, it restricts date output for Forecast and History API
14+
Date time.Time `json:"dt"`
1115
}

weather_api.go

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@ import (
44
"encoding/json"
55
"fmt"
66
"net/http"
7-
"time"
87

98
"github.com/kashifkhan0771/go-weather/config"
109
"github.com/kashifkhan0771/go-weather/models"
1110
)
1211

1312
// GetCurrentWeather return current weather response based on the option query
1413
func (c WeatherAPIConfig) GetCurrentWeather(options Options) (*models.WeatherResponse, error) {
15-
if options.Query == "" {
16-
return nil, fmt.Errorf("query is empty")
14+
if !validateQuery(options.Query) {
15+
return nil, fmt.Errorf("invalid query parameter")
1716
}
1817

1918
url := fmt.Sprintf("%s%s?q=%s", config.BaseURL, config.CurrentWeatherJSON, options.Query)
@@ -25,27 +24,44 @@ func (c WeatherAPIConfig) GetCurrentWeather(options Options) (*models.WeatherRes
2524

2625
defer resp.Body.Close()
2726

28-
// Check response status code
29-
if resp.StatusCode != http.StatusOK {
27+
// Decode JSON response body
28+
var weatherResp models.WeatherResponse
29+
err = json.NewDecoder(resp.Body).Decode(&weatherResp)
30+
if err != nil {
31+
return nil, err
32+
}
33+
34+
return &weatherResp, nil
35+
}
36+
37+
func (c WeatherAPIConfig) WeatherHistory(options Options) (*models.WeatherResponse, error) {
38+
if !validateQuery(options.Query) {
39+
return nil, fmt.Errorf("invalid query parameter")
40+
} else if !validateDate(options.Date) {
41+
return nil, fmt.Errorf("invalid date parameter")
42+
}
43+
44+
url := fmt.Sprintf("%s%s?q=%s&dt=%s", config.BaseURL, config.HistoryWeatherJSON, options.Query, options.Date.Format("2006-01-02"))
45+
46+
resp, err := c.makeRequest(http.MethodGet, url)
47+
if err != nil {
3048
return nil, err
3149
}
3250

51+
defer resp.Body.Close()
52+
3353
// Decode JSON response body
34-
var weatherResp *models.WeatherResponse
54+
var weatherResp models.WeatherResponse
3555
err = json.NewDecoder(resp.Body).Decode(&weatherResp)
3656
if err != nil {
3757
return nil, err
3858
}
3959

40-
return weatherResp, nil
60+
return &weatherResp, nil
4161
}
4262

4363
// makeRequest is a helper function for making API requests.
4464
func (c WeatherAPIConfig) makeRequest(method, url string) (*http.Response, error) {
45-
client := &http.Client{
46-
Timeout: time.Second * config.APIsTimeout,
47-
}
48-
4965
req, err := http.NewRequest(method, url, http.NoBody)
5066
if err != nil {
5167
return nil, err
@@ -54,9 +70,13 @@ func (c WeatherAPIConfig) makeRequest(method, url string) (*http.Response, error
5470
req.Header.Set("key", c.XApiKey)
5571

5672
// Send request
57-
resp, err := client.Do(req)
73+
resp, err := c.HttpClient.Do(req)
5874
if err != nil {
59-
return nil, err
75+
return nil, fmt.Errorf("HTTP request failed: %w", err)
76+
}
77+
78+
if resp.StatusCode != http.StatusOK {
79+
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
6080
}
6181

6282
return resp, nil

weather_api_config.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
11
package go_weather
22

3+
import (
4+
"errors"
5+
"net/http"
6+
"time"
7+
8+
"github.com/kashifkhan0771/go-weather/config"
9+
)
10+
311
// WeatherAPIConfig has the configurations required to call the APIs
412
type WeatherAPIConfig struct {
513
// XApiKey can be obtained from: https://www.weatherapi.com/ after you log in
6-
XApiKey string `json:"key"`
14+
XApiKey string `json:"key"`
15+
HttpClient *http.Client `json:"-"`
16+
}
17+
18+
// NewWeatherAPIConfig creates a WeatherAPIConfig with apiKey passed.
19+
func NewWeatherAPIConfig(apiKey string) (*WeatherAPIConfig, error) {
20+
if apiKey == "" {
21+
return nil, errors.New("API key cannot be empty")
22+
}
23+
24+
return &WeatherAPIConfig{
25+
XApiKey: apiKey,
26+
HttpClient: &http.Client{Timeout: time.Second * config.APIsTimeout},
27+
}, nil
728
}

0 commit comments

Comments
 (0)