weather-api/api/rest-api.go
2021-04-02 21:01:22 +02:00

154 lines
4.2 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"weather-data/storage"
"weather-data/weathersource"
"github.com/google/uuid"
"github.com/gorilla/mux"
)
type weatherRestApi struct {
connection string
weaterStorage storage.WeatherStorage
weatherSource weathersource.WeatherSourceBase
sensorRegistry storage.SensorRegistry
}
//SetupAPI sets the REST-API up
func NewRestAPI(connection string, weatherStorage storage.WeatherStorage, sensorRegistry storage.SensorRegistry) *weatherRestApi {
api := new(weatherRestApi)
api.connection = connection
api.weaterStorage = weatherStorage
api.sensorRegistry = sensorRegistry
return api
}
//Start a new Rest-API instance
func (api *weatherRestApi) Start() error {
handler := api.handleRequests()
return http.ListenAndServe(api.connection, handler) // http.ListenAndServe(api.connection, handler)
}
func (api *weatherRestApi) Close() {
}
func (api *weatherRestApi) handleRequests() *mux.Router {
router := mux.NewRouter()
router.HandleFunc("/", api.homePageHandler)
router.HandleFunc("/random", api.randomWeatherHandler)
router.HandleFunc("/randomlist", api.randomWeatherListHandler)
router.HandleFunc("/addData", api.addDataHandler)
router.HandleFunc("/getData/{id}", api.getData)
router.HandleFunc("/registerWeatherSensor/{name}", api.registerWeatherSensor)
return router
}
func caselessMatcher(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.URL.Path = strings.ToLower(r.URL.Path)
next.ServeHTTP(w, r)
})
}
func (api *weatherRestApi) getData(w http.ResponseWriter, r *http.Request) {
w.Header().Add("content-type", "application/json")
vars := mux.Vars(r)
id := vars["id"]
query, err := storage.ParseFromUrlQuery(r.URL.Query())
if err != nil {
http.Error(w, fmt.Sprintf("could not parse query: %v", err.Error()), http.StatusBadRequest)
return
}
query.SensorId, err = uuid.Parse(id)
if err != nil {
http.Error(w, "could not parse uuid", http.StatusBadRequest)
return
}
data, err := api.weaterStorage.GetData(query)
if err != nil {
http.Error(w, "", http.StatusBadRequest)
return
}
res := storage.GetOnlyQueriedFields(data, query)
json.NewEncoder(w).Encode(res)
}
func (api *weatherRestApi) randomWeatherHandler(w http.ResponseWriter, r *http.Request) {
datapoint := storage.NewRandomWeatherData(uuid.Nil)
w.Header().Add("content-type", "application/json")
json.NewEncoder(w).Encode(datapoint)
}
func (api *weatherRestApi) randomWeatherListHandler(w http.ResponseWriter, r *http.Request) {
var datapoints = make([]storage.WeatherData, 0)
for i := 0; i < 10; i++ {
datapoints = append(datapoints, storage.NewRandomWeatherData(uuid.Nil))
}
w.Header().Add("content-type", "application/json")
json.NewEncoder(w).Encode(datapoints)
}
func (api *weatherRestApi) addDataHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "only POST-Method allowed", http.StatusMethodNotAllowed)
return
}
var data storage.WeatherData
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
err = api.addNewWeatherData(data)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
}
func (api *weatherRestApi) homePageHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the Weather API!")
}
func (api *weatherRestApi) registerWeatherSensor(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "only POST-Method allowed", http.StatusMethodNotAllowed)
return
}
w.Header().Add("content-type", "application/json")
vars := mux.Vars(r)
name := vars["name"]
sensor, err := api.sensorRegistry.RegisterSensorByName(name)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
json.NewEncoder(w).Encode(sensor)
}
//AddNewWeatherDataCallback adds a new callbackMethod for incoming weather data
func (api *weatherRestApi) AddNewWeatherDataCallback(callback weathersource.NewWeatherDataCallbackFunc) {
api.weatherSource.AddNewWeatherDataCallback(callback)
}
func (api *weatherRestApi) addNewWeatherData(weatherData storage.WeatherData) error {
return api.weatherSource.NewWeatherData(weatherData)
}