diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-11-01 22:05:28 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-11-01 22:05:28 -0400 |
| commit | 125d883d2380e70aab9a1d63753a1e10fb80032b (patch) | |
| tree | 56daa0604d850674c7a1669c00a664e93c848deb | |
| parent | 7e8fc5d6e0f50201a692c9c6468ff56c69fcdf70 (diff) | |
| download | soen422-125d883d2380e70aab9a1d63753a1e10fb80032b.zip | |
implement server GET /humidity
| -rw-r--r-- | record.go | 60 | ||||
| -rw-r--r-- | server.go | 51 |
2 files changed, 111 insertions, 0 deletions
diff --git a/record.go b/record.go new file mode 100644 index 0000000..9051146 --- /dev/null +++ b/record.go @@ -0,0 +1,60 @@ +package main + +import ( + "time" +) + +type Record[T any] struct { + put chan<- T + get chan<- chan T + getRecent chan<- chan T +} + +type entry[T any] struct { + t time.Time + v T +} + +func newRecord[T any]() Record[T] { + put := make(chan T) + get := make(chan chan T) + getRecent := make(chan chan T) + + go func() { + var entries []entry[T] + + for { + select { + case v, ok := <-put: + if !ok { + return + } + entries = append(entries, entry[T]{time.Now(), v}) + case c, ok := <-get: + if !ok { + return + } + for _, e := range entries { + c <- e.v + } + close(c) + case c, ok := <-getRecent: + if !ok { + return + } + if len(entries) > 0 { + c <- entries[len(entries)-1].v + } + close(c) + } + } + }() + + return Record[T]{put, get, getRecent} +} + +func (l Record[T]) Close() { + close(l.put) + close(l.get) + close(l.getRecent) +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..67d153d --- /dev/null +++ b/server.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "log" + "net/http" +) + +const addr = ":9090" + +type humidityHandler struct { + humidity Record[float32] +} + +func newHumidityHandler() humidityHandler { + return humidityHandler{newRecord[float32]()} +} + +func (h *humidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + h.get(w, r) + case http.MethodPost: + h.post(w, r) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + fmt.Fprintf(w, "invalid method: '%s'", r.Method) + } +} + +func (h *humidityHandler) get(w http.ResponseWriter, r *http.Request) { + c := make(chan float32) + h.humidity.getRecent <- c + humidity, ok := <-c + if !ok { + w.WriteHeader(http.StatusGone) + fmt.Fprintf(w, "no humidity data stored on server") + return + } + fmt.Fprintf(w, "%f", humidity) +} + +func (h *humidityHandler) post(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +func main() { + http.Handle("/humidity", new(humidityHandler)) + fmt.Printf("Listening on %s...\n", addr) + log.Fatal(http.ListenAndServe(addr, nil)) +} |