The schema defines the absence of state->open to represent the unknown state. Previously it was not possible to explicitly set this state via the HTTP endpoints. types.SpaceAPIState.Open is now an enum which is either unknown, closed, or open. Custom IsZero() and MarshalJSON() methods on the type ensure marshaling the value yields a boolean for open/closed and an empty byte slice for unknown (resulting in the field being absent from the final response). The handlers.StateOpenDELETE() function has been added to expose this behavior. Switching to encoding/json/v2 required raising the minimum Go version in go.mod to 1.27. Closes: CCCHH/spaceapid!37 Fixes: CCCHH/spaceapid#38
98 lines
2.5 KiB
Go
98 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"git.hamburg.ccc.de/ccchh/spaceapid/config"
|
|
"git.hamburg.ccc.de/ccchh/spaceapid/handlers"
|
|
"git.hamburg.ccc.de/ccchh/spaceapid/persistence"
|
|
"git.hamburg.ccc.de/ccchh/spaceapid/types"
|
|
"git.hamburg.ccc.de/ccchh/spaceapid/util"
|
|
)
|
|
|
|
var (
|
|
flagHelp bool
|
|
version string
|
|
)
|
|
|
|
func init() {
|
|
flag.BoolVar(&flagHelp, "h", false, "Print help output")
|
|
}
|
|
|
|
func main() {
|
|
if version == "" {
|
|
version = "unknown"
|
|
}
|
|
log.Println("SpaceAPId version", version)
|
|
|
|
flag.Parse()
|
|
|
|
if flagHelp {
|
|
flag.PrintDefaults()
|
|
os.Exit(0)
|
|
}
|
|
|
|
// Get spaceapid configuration
|
|
conf := config.ParseConfiguration()
|
|
|
|
// Merge old state if present
|
|
persistence.MergeOldState(&conf.Response)
|
|
|
|
// Register signal handler
|
|
sc := make(chan os.Signal, 1)
|
|
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM)
|
|
go func(resp *types.SpaceAPIResponse) {
|
|
<-sc
|
|
log.Println("Saving state and shutting down...")
|
|
persistence.SaveCurrentState(*resp)
|
|
os.Exit(0)
|
|
}(&conf.Response)
|
|
|
|
// Root handler
|
|
http.HandleFunc("GET /{$}",
|
|
handlers.Root(&conf.Response),
|
|
)
|
|
// state->open
|
|
http.HandleFunc("PUT /state/open",
|
|
handlers.StateOpenPUT(conf.Credentials, conf.Dynamic.State.Open.AllowedCredentials, &conf.Response.State),
|
|
)
|
|
http.HandleFunc("DELETE /state/open",
|
|
handlers.StateOpenDELETE(conf.Credentials, conf.Dynamic.State.Open.AllowedCredentials, &conf.Response.State),
|
|
)
|
|
// state->message
|
|
http.HandleFunc("PUT /state/message",
|
|
handlers.StateMessagePUT(conf.Credentials, conf.Dynamic.State.Open.AllowedCredentials, &conf.Response.State),
|
|
)
|
|
http.HandleFunc("DELETE /state/message",
|
|
handlers.StateMessageDELETE(conf.Credentials, conf.Dynamic.State.Open.AllowedCredentials, &conf.Response.State),
|
|
)
|
|
// Register handlers for environmental sensors
|
|
for sensorType, envSensorConfigs := range conf.Dynamic.Sensors {
|
|
for i, envSensorConfig := range envSensorConfigs {
|
|
urlPattern := util.GetSensorURLPath(
|
|
sensorType, envSensorConfig.SensorData.Location, envSensorConfig.SensorData.Name,
|
|
)
|
|
http.HandleFunc(
|
|
"PUT "+urlPattern,
|
|
handlers.EnvironmentSensorPUT(
|
|
conf.Credentials, envSensorConfig.AllowedCredentials, &conf.Response.Sensors[sensorType][i],
|
|
),
|
|
)
|
|
http.HandleFunc(
|
|
"DELETE "+urlPattern,
|
|
handlers.EnvironmentSensorDELETE(
|
|
conf.Credentials, envSensorConfig.AllowedCredentials, &conf.Response.Sensors[sensorType][i],
|
|
),
|
|
)
|
|
}
|
|
}
|
|
|
|
// Start webserver
|
|
log.Println("Starting HTTP server...")
|
|
log.Fatalln(http.ListenAndServe(":8080", nil))
|
|
}
|