diff options
Diffstat (limited to 'internal/handler')
-rw-r--r-- | internal/handler/auth.go | 15 | ||||
-rw-r--r-- | internal/handler/contract.go | 12 | ||||
-rw-r--r-- | internal/handler/crud.go | 88 | ||||
-rw-r--r-- | internal/handler/events.go | 16 | ||||
-rw-r--r-- | internal/handler/handler.go | 11 | ||||
-rw-r--r-- | internal/handler/hearthbeat.go | 15 |
6 files changed, 62 insertions, 95 deletions
diff --git a/internal/handler/auth.go b/internal/handler/auth.go deleted file mode 100644 index c66eeb7..0000000 --- a/internal/handler/auth.go +++ /dev/null @@ -1,15 +0,0 @@ -package handler - -import ( - "fmt" - - "github.com/go-chi/jwtauth/v5" -) - -var tokenAuth *jwtauth.JWTAuth - -func init() { - tokenAuth = jwtauth.New("HS256", []byte("secret"), nil) - _, tokenString, _ := tokenAuth.Encode(map[string]interface{}{"user_id": 123}) - fmt.Printf("DEBUG: a sample jwt is %s\n\n", tokenString) -} diff --git a/internal/handler/contract.go b/internal/handler/contract.go index 8887be8..38280cf 100644 --- a/internal/handler/contract.go +++ b/internal/handler/contract.go @@ -1,13 +1,13 @@ package handler import ( - "net/http" + "context" - "github.com/go-chi/chi/v5" + "go.neonxp.dev/djson/internal/command" + "go.neonxp.dev/json" ) -type Handler interface { - HandleCRUD(r chi.Router) - HandleEvents(r chi.Router) - Hearthbeat(w http.ResponseWriter, r *http.Request) +type Core interface { + Apply(ctx context.Context, mutation *command.Mutation) error + Query(ctx context.Context, query []string) (json.Node, error) } diff --git a/internal/handler/crud.go b/internal/handler/crud.go index 4ab0c7f..b12f68a 100644 --- a/internal/handler/crud.go +++ b/internal/handler/crud.go @@ -1,37 +1,35 @@ package handler import ( + "fmt" "io" "net/http" - "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" - "go.neonxp.dev/djson/internal/model" - "go.neonxp.dev/json" + "go.neonxp.dev/djson/internal/command" + "go.neonxp.dev/objectid" ) -func (h *handler) HandleCRUD(r chi.Router) { - r.Use(middleware.CleanPath) - r.Use(middleware.StripSlashes) +func (h *handler) HandleCRUD(router chi.Router) { + router.Use(middleware.CleanPath) + router.Use(middleware.StripSlashes) - r.Get("/*", func(w http.ResponseWriter, r *http.Request) { + router.Get("/*", func(w http.ResponseWriter, r *http.Request) { rctx := chi.RouteContext(r.Context()) - res, err := h.core.Get(parsePath(rctx.RoutePath)) - if err != nil { - writeError(http.StatusNotFound, err, w) - return - } - result, err := res.MarshalJSON() + path := parsePath(rctx.RoutePath) + + node, err := h.core.Query(r.Context(), path) if err != nil { - writeError(http.StatusInternalServerError, err, w) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf(`{"error":"%s"}`, err.Error()))) return } w.WriteHeader(http.StatusOK) - _, _ = w.Write(result) + _, _ = w.Write([]byte(node.String())) }) - r.Post("/*", func(w http.ResponseWriter, r *http.Request) { + router.Post("/*", func(w http.ResponseWriter, r *http.Request) { rctx := chi.RouteContext(r.Context()) path := parsePath(rctx.RoutePath) jsonBody, err := io.ReadAll(r.Body) @@ -40,25 +38,23 @@ func (h *handler) HandleCRUD(r chi.Router) { return } r.Body.Close() - node, err := json.Unmarshal(jsonBody) - if err != nil { - writeError(http.StatusBadRequest, err, w) - return - } - mutation := &model.Mutation{ - Date: time.Now(), - Type: model.Create, + + mutation := command.Mutation{ + ID: objectid.New(), + Type: command.Create, Path: path, - Body: node, + Data: string(jsonBody), } - if err := h.core.Mutate(r.Context(), mutation); err != nil { - writeError(http.StatusInternalServerError, err, w) + if err := h.core.Apply(r.Context(), &mutation); err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf(`{"error":"%s"}`, err.Error()))) return } + w.WriteHeader(http.StatusCreated) }) - r.Patch("/*", func(w http.ResponseWriter, r *http.Request) { + router.Patch("/*", func(w http.ResponseWriter, r *http.Request) { rctx := chi.RouteContext(r.Context()) path := parsePath(rctx.RoutePath) jsonBody, err := io.ReadAll(r.Body) @@ -67,37 +63,37 @@ func (h *handler) HandleCRUD(r chi.Router) { return } r.Body.Close() - node, err := json.Unmarshal(jsonBody) - if err != nil { - writeError(http.StatusBadRequest, err, w) - return - } - mutation := &model.Mutation{ - Date: time.Now(), - Type: model.Merge, + + mutation := command.Mutation{ + ID: objectid.New(), + Type: command.Merge, Path: path, - Body: node, + Data: string(jsonBody), } - if err := h.core.Mutate(r.Context(), mutation); err != nil { - writeError(http.StatusInternalServerError, err, w) + if err := h.core.Apply(r.Context(), &mutation); err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf(`{"error":"%s"}`, err.Error()))) return } + w.WriteHeader(http.StatusOK) }) - r.Delete("/*", func(w http.ResponseWriter, r *http.Request) { + router.Delete("/*", func(w http.ResponseWriter, r *http.Request) { rctx := chi.RouteContext(r.Context()) path := parsePath(rctx.RoutePath) - mutation := &model.Mutation{ - Date: time.Now(), - Type: model.Remove, + + mutation := command.Mutation{ + ID: objectid.New(), + Type: command.Remove, Path: path, - Body: nil, } - if err := h.core.Mutate(r.Context(), mutation); err != nil { - writeError(http.StatusInternalServerError, err, w) + if err := h.core.Apply(r.Context(), &mutation); err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf(`{"error":"%s"}`, err.Error()))) return } + w.WriteHeader(http.StatusNoContent) }) } diff --git a/internal/handler/events.go b/internal/handler/events.go index 299971d..43de3c4 100644 --- a/internal/handler/events.go +++ b/internal/handler/events.go @@ -1,20 +1,22 @@ package handler import ( + "encoding/json" "fmt" "net/http" "strings" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" - dmodel "go.neonxp.dev/djson/internal/model" + + "go.neonxp.dev/djson/internal/command" ) func (h *handler) HandleEvents(r chi.Router) { r.Route("/sse", func(r chi.Router) { r.Get("/*", func(w http.ResponseWriter, r *http.Request) { - h.receiveEvents(w, r, func(ev *dmodel.Mutation) { - message, _ := ev.Body.MarshalJSON() + h.receiveEvents(w, r, func(ev *command.Mutation) { + message, _ := json.Marshal(ev.Data) fmt.Fprintf( w, `event: %s\ndata: {"path":"%s","data":%s}\n\n`, @@ -27,8 +29,8 @@ func (h *handler) HandleEvents(r chi.Router) { }) r.Route("/json", func(r chi.Router) { r.Get("/*", func(w http.ResponseWriter, r *http.Request) { - h.receiveEvents(w, r, func(ev *dmodel.Mutation) { - message, _ := ev.Body.MarshalJSON() + h.receiveEvents(w, r, func(ev *command.Mutation) { + message, _ := json.Marshal(ev.Data) fmt.Fprintf( w, `{"event":"%s","path":"%s","data":"%s"}\n`, @@ -44,7 +46,7 @@ func (h *handler) HandleEvents(r chi.Router) { func (h *handler) receiveEvents( w http.ResponseWriter, r *http.Request, - render func(ev *dmodel.Mutation), + render func(ev *command.Mutation), ) { flusher := w.(http.Flusher) w.Header().Set("Content-Type", "application/x-ndjson") @@ -53,7 +55,7 @@ func (h *handler) receiveEvents( w.Header().Set("Access-Control-Allow-Origin", "*") rctx := chi.RouteContext(r.Context()) path := parsePath(rctx.RoutePath) - ch := make(chan dmodel.Mutation) + ch := make(chan command.Mutation) reqID := middleware.GetReqID(r.Context()) h.events.Subscribe(path, reqID, ch) defer h.events.Unsubscribe(path, reqID) diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 11c1936..bd8a2c1 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -4,14 +4,10 @@ import ( "net/http" "strings" - "go.neonxp.dev/json" - jsonModel "go.neonxp.dev/json/model" - "go.neonxp.dev/djson/internal/events" - "go.neonxp.dev/djson/internal/tree" ) -func New(core tree.Core, eventsDispatcher events.Dispatcher) Handler { +func New(core Core, eventsDispatcher events.Dispatcher) *handler { return &handler{ core: core, events: eventsDispatcher, @@ -19,13 +15,12 @@ func New(core tree.Core, eventsDispatcher events.Dispatcher) Handler { } type handler struct { - core tree.Core + core Core events events.Dispatcher } func writeError(code int, err error, w http.ResponseWriter) { - jsonErr, _ := json.Marshal(jsonModel.NewNode(err.Error())) - _, _ = w.Write(jsonErr) + _, _ = w.Write([]byte(err.Error())) } func parsePath(nodePath string) []string { diff --git a/internal/handler/hearthbeat.go b/internal/handler/hearthbeat.go index 014880e..22f6c3c 100644 --- a/internal/handler/hearthbeat.go +++ b/internal/handler/hearthbeat.go @@ -2,21 +2,10 @@ package handler import ( "net/http" - - "go.neonxp.dev/djson/internal/tree" ) func (h *handler) Hearthbeat(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") - switch h.core.State() { - case tree.Ready: - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(".")) - case tree.Failed: - w.WriteHeader(http.StatusInternalServerError) - _, _ = w.Write([]byte("start failed")) - case tree.Running: - w.WriteHeader(http.StatusServiceUnavailable) - _, _ = w.Write([]byte("starting...")) - } + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(".")) } |