summaryrefslogtreecommitdiffstats
path: root/api/dto
diff options
context:
space:
mode:
Diffstat (limited to 'api/dto')
-rw-r--r--api/dto/entry.go9
-rw-r--r--api/dto/response.go38
-rw-r--r--api/dto/util.go54
3 files changed, 101 insertions, 0 deletions
diff --git a/api/dto/entry.go b/api/dto/entry.go
new file mode 100644
index 0000000..85e39f3
--- /dev/null
+++ b/api/dto/entry.go
@@ -0,0 +1,9 @@
+package dto
+
+type CreateEntryRequest struct {
+ Title string `json:"title"`
+ Kind string `json:"kind"`
+ Url string `json:"url"`
+ Description string `json:"description"`
+ Token string `json:"token"`
+}
diff --git a/api/dto/response.go b/api/dto/response.go
new file mode 100644
index 0000000..2c13218
--- /dev/null
+++ b/api/dto/response.go
@@ -0,0 +1,38 @@
+package dto
+
+import "fmt"
+
+type Response interface {
+ Error() string
+ Status() int
+}
+
+type OkResponse struct {
+ Code int `json:"code"`
+ Data interface{} `json:"data,omitempty"`
+}
+
+var _ Response = (*OkResponse)(nil)
+
+type ErrorResponse struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+}
+
+var _ Response = (*ErrorResponse)(nil)
+
+func (r *OkResponse) Status() int {
+ return r.Code
+}
+
+func (r *OkResponse) Error() string {
+ return fmt.Sprintf("HTTP status %d", r.Code)
+}
+
+func (r *ErrorResponse) Status() int {
+ return r.Code
+}
+
+func (r *ErrorResponse) Error() string {
+ return fmt.Sprintf("HTTP status %d: %s", r.Code, r.Message)
+}
diff --git a/api/dto/util.go b/api/dto/util.go
new file mode 100644
index 0000000..651f026
--- /dev/null
+++ b/api/dto/util.go
@@ -0,0 +1,54 @@
+package dto
+
+import (
+ "encoding/json"
+ "fmt"
+ "log/slog"
+ "net/http"
+
+ "github.com/go-playground/validator/v10"
+)
+
+var validate = validator.New(validator.WithRequiredStructEnabled())
+
+func ReadDto(r *http.Request, o interface{}) Response {
+ decoder := json.NewDecoder(r.Body)
+ if err := decoder.Decode(o); err != nil {
+ return &ErrorResponse{
+ Code: http.StatusBadRequest,
+ Message: fmt.Errorf("Invalid request (%w)", err).Error(),
+ }
+ }
+
+ if err := validate.Struct(o); err != nil {
+ return &ErrorResponse{
+ Code: http.StatusBadRequest,
+ Message: err.Error(),
+ }
+ }
+
+ return nil
+}
+
+func WrapResponseFunc(dtoFunc func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ WriteDto(w, r, dtoFunc(w, r))
+ }
+}
+
+func WriteDto(w http.ResponseWriter, r *http.Request, err error) {
+ if o, ok := err.(Response); ok {
+ data, err := json.Marshal(o)
+ if err != nil {
+ w.WriteHeader(500)
+ slog.Error("could not serialise JSON", "error", err)
+ return
+ }
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(o.Status())
+ w.Write(data)
+ } else {
+ w.WriteHeader(500)
+ slog.Error("internal server error handling request", "error", err)
+ }
+}