summaryrefslogtreecommitdiff
path: root/internal/handler
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handler')
-rw-r--r--internal/handler/auth.go15
-rw-r--r--internal/handler/contract.go12
-rw-r--r--internal/handler/crud.go88
-rw-r--r--internal/handler/events.go16
-rw-r--r--internal/handler/handler.go11
-rw-r--r--internal/handler/hearthbeat.go15
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("."))
}