summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Dessaux2024-10-01 17:32:14 +0200
committerJulien Dessaux2024-10-02 23:23:43 +0200
commitd4a82f610cd226f55bf98201dbd06aa05c2cf33c (patch)
tree79c25efdbac23a649da89e3ebc5ff2ac7c999977
parentfeat(logger): implement a logger middleware (diff)
downloadtfstated-d4a82f610cd226f55bf98201dbd06aa05c2cf33c.tar.gz
tfstated-d4a82f610cd226f55bf98201dbd06aa05c2cf33c.tar.bz2
tfstated-d4a82f610cd226f55bf98201dbd06aa05c2cf33c.zip
feat(tfstated): add json encoding and decoding helpers
-rw-r--r--cmd/tfstated/get.go11
-rw-r--r--cmd/tfstated/helpers.go36
-rw-r--r--cmd/tfstated/post.go12
3 files changed, 46 insertions, 13 deletions
diff --git a/cmd/tfstated/get.go b/cmd/tfstated/get.go
index 6de78a5..7d54970 100644
--- a/cmd/tfstated/get.go
+++ b/cmd/tfstated/get.go
@@ -12,21 +12,20 @@ import (
func handleGet(db *database.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-store, no-cache")
- w.Header().Set("Content-Type", "application/json")
if r.URL.Path == "/" {
- w.WriteHeader(http.StatusBadRequest)
- _, _ = w.Write([]byte("{\"msg\": \"No state path provided, cannot GET /\"}"))
+ _ = errorResponse(w, http.StatusBadRequest,
+ fmt.Errorf("no state path provided, cannot GET /"))
return
}
if data, err := db.GetState(r.URL.Path); err != nil {
if errors.Is(err, sql.ErrNoRows) {
- w.WriteHeader(http.StatusNotFound)
+ _ = errorResponse(w, http.StatusNotFound,
+ fmt.Errorf("state path not found: %s", r.URL.Path))
} else {
- w.WriteHeader(http.StatusInternalServerError)
+ _ = errorResponse(w, http.StatusInternalServerError, err)
}
- _, _ = w.Write([]byte(fmt.Sprintf("{\"msg\": \"%+v\"}", err)))
} else {
w.WriteHeader(http.StatusOK)
_, _ = w.Write(data)
diff --git a/cmd/tfstated/helpers.go b/cmd/tfstated/helpers.go
new file mode 100644
index 0000000..33e14a4
--- /dev/null
+++ b/cmd/tfstated/helpers.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "log/slog"
+ "net/http"
+)
+
+func decode(r *http.Request, data any) error {
+ if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
+ return fmt.Errorf("failed to decode json: %w", err)
+ }
+ return nil
+}
+
+func encode(w http.ResponseWriter, status int, data any) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(status)
+ if err := json.NewEncoder(w).Encode(data); err != nil {
+ slog.Error("failed to encode json", "err", err)
+ return fmt.Errorf("failed to encode json: %w", err)
+ }
+ return nil
+}
+
+func errorResponse(w http.ResponseWriter, status int, err error) error {
+ type errorResponse struct {
+ Msg string `json:"msg"`
+ Status int `json:"status"`
+ }
+ return encode(w, status, &errorResponse{
+ Msg: fmt.Sprintf("%+v", err),
+ Status: status,
+ })
+}
diff --git a/cmd/tfstated/post.go b/cmd/tfstated/post.go
index e47f5ad..b88109e 100644
--- a/cmd/tfstated/post.go
+++ b/cmd/tfstated/post.go
@@ -10,21 +10,19 @@ import (
func handlePost(db *database.DB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
if r.URL.Path == "/" {
- w.WriteHeader(http.StatusBadRequest)
- _, _ = w.Write([]byte("{\"msg\": \"No state path provided, cannot POST /\"}"))
+ _ = errorResponse(w, http.StatusBadRequest,
+ fmt.Errorf("no state path provided, cannot POST /"),
+ )
return
}
data, err := io.ReadAll(r.Body)
if err != nil {
- w.WriteHeader(http.StatusBadRequest)
- _, _ = w.Write([]byte(fmt.Sprintf("{\"msg\": \"failed to read request body: %+v\"}", err)))
+ _ = errorResponse(w, http.StatusBadRequest, err)
return
}
if err := db.SetState(r.URL.Path, data); err != nil {
- w.WriteHeader(http.StatusInternalServerError)
- _, _ = w.Write([]byte(fmt.Sprintf("{\"msg\": \"%+v\"}", err)))
+ _ = errorResponse(w, http.StatusInternalServerError, err)
} else {
w.WriteHeader(http.StatusOK)
}