1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
package main
import (
"embed"
"flag"
"fmt"
"log"
"net/http"
"text/template"
)
//go:embed simple.css/simple.css templates/index.html
var static embed.FS
func main() {
configPath := parseFlags()
c := parseConfig(configPath)
http.HandleFunc("/", index(c.Devices))
http.HandleFunc("/api", api())
http.Handle("/static/", http.StripPrefix("/static/",
http.FileServer(http.FS(static))))
fmt.Printf("Serving at http://%s\n", c.Web.Listen)
log.Fatal(http.ListenAndServe(c.Web.Listen.String(), nil))
}
// parseFlags() handles command line interface (CLI) flags.
func parseFlags() string {
var r string
flag.StringVar(&r, "c", "/etc/webiot/config.json",
"path to configuration file")
flag.Parse()
return r
}
// index() returns a HTTP handler for the index page.
func index(devices DevicesConfig) func(http.ResponseWriter, *http.Request) {
tmpl, err := template.ParseFS(static, "templates/index.html")
if err != nil {
log.Fatal(err)
}
return func(w http.ResponseWriter, r *http.Request) {
err = tmpl.Execute(w, devices)
if err != nil {
http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
return
}
}
}
// api() returns the HTTP handler for the API endpoint.
func api() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
// TODO assert correct HTTP method
errHost, host := assertSingleParam(r, "host")
errState, state := assertSingleParam(r, "state")
if (errHost != nil) || (errState != nil) {
http.Error(w,
"Provide exactly one host and one state parameter!", 400)
return
}
err := set(host, state)
if err != nil {
http.Error(w, "Could not set WiFi plug.", 500)
} else {
fmt.Fprint(w, "ok")
}
}
}
// assertSingleParam() returns the value of given URL key and panics if there
// is not exactly one match for this key.
func assertSingleParam(r *http.Request, key string) (error, string) {
values := r.URL.Query()[key]
if len(values) != 1 {
return fmt.Errorf("Provide exactly one '%s' parameter!", key), ""
}
return nil, values[0]
}
|