github.com/blong14/gache@v0.0.0-20240124023949-89416fd8bbfa/internal/server/handlers.go (about) 1 package server 2 3 import ( 4 "context" 5 "encoding/json" 6 "io" 7 "log" 8 "net/http" 9 10 gdb "github.com/blong14/gache/internal/db" 11 ghttp "github.com/blong14/gache/internal/io/http" 12 gproxy "github.com/blong14/gache/internal/proxy" 13 ) 14 15 type ErrorResponse struct { 16 Error string `json:"error"` 17 } 18 19 func HealthzService(w http.ResponseWriter, _ *http.Request) { 20 if _, err := io.WriteString(w, "ok"); err != nil { 21 log.Println(err) 22 } 23 } 24 25 type GetValueResponse struct { 26 Status string `json:"status"` 27 Key string `json:"key"` 28 Value string `json:"value"` 29 } 30 31 func getValueService(proxy *gproxy.QueryProxy) http.HandlerFunc { 32 return func(w http.ResponseWriter, r *http.Request) { 33 urlQuery := r.URL.Query() 34 if !urlQuery.Has("key") { 35 err := ErrorResponse{Error: "missing key"} 36 ghttp.MustWriteJSON(w, r, http.StatusBadRequest, err) 37 return 38 } 39 key := urlQuery.Get("key") 40 table := urlQuery.Get("table") 41 if table == "" { 42 table = "default" 43 } 44 ctx, cancel := context.WithCancel(r.Context()) 45 defer cancel() 46 query, _ := gdb.NewGetValueQuery(ctx, []byte(table), []byte(key)) 47 proxy.Send(ctx, query) 48 result := query.GetResponse() 49 var resp GetValueResponse 50 var status int 51 switch { 52 case !result.Success: 53 status = http.StatusNotFound 54 resp.Status = "not found" 55 resp.Key = key 56 default: 57 status = http.StatusOK 58 resp.Status = "ok" 59 resp.Key = key 60 resp.Value = string(result.Value) 61 } 62 ghttp.MustWriteJSON(w, r, status, resp) 63 } 64 } 65 66 type SetValueRequest struct { 67 Table string `json:"table"` 68 Key string `json:"key"` 69 Value string `json:"value"` 70 } 71 72 type SetValueResponse struct { 73 Status string `json:"status"` 74 Key string `json:"key"` 75 Value string `json:"value"` 76 } 77 78 func setValueService(proxy *gproxy.QueryProxy) http.HandlerFunc { 79 return func(w http.ResponseWriter, r *http.Request) { 80 body := r.Body 81 if body == nil { 82 resp := ErrorResponse{Error: "server error"} 83 ghttp.MustWriteJSON(w, r, http.StatusInternalServerError, resp) 84 return 85 } 86 defer func() { _ = body.Close() }() 87 decoder := json.NewDecoder(body) 88 var req SetValueRequest 89 if err := decoder.Decode(&req); err != nil { 90 resp := ErrorResponse{Error: err.Error()} 91 ghttp.MustWriteJSON(w, r, http.StatusUnprocessableEntity, resp) 92 return 93 } 94 ctx, cancel := context.WithCancel(r.Context()) 95 defer cancel() 96 query, _ := gdb.NewSetValueQuery(ctx, []byte(req.Table), []byte(req.Key), []byte(req.Value)) 97 proxy.Send(ctx, query) 98 result := query.GetResponse() 99 var resp SetValueResponse 100 var status int 101 switch { 102 case !result.Success: 103 status = http.StatusNotFound 104 resp.Status = "not found" 105 resp.Key = req.Key 106 default: 107 status = http.StatusCreated 108 resp.Status = "created" 109 resp.Key = req.Key 110 resp.Value = string(result.Value) 111 } 112 ghttp.MustWriteJSON(w, r, status, resp) 113 } 114 } 115 116 func HTTPHandlers(proxy *gproxy.QueryProxy) ghttp.Handler { 117 return map[string]http.HandlerFunc{ 118 "/healthz": HealthzService, 119 "/get": MustBe(http.MethodGet, getValueService(proxy)), 120 "/set": MustBe(http.MethodPost, setValueService(proxy)), 121 } 122 }