devices: added create and update endpoint
This commit is contained in:
parent
c8c8cc892d
commit
9eb6923398
|
@ -2,14 +2,28 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/tigorlazuardi/redmage/db/queries"
|
"github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/tigorlazuardi/redmage/models"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeviceCreateParams = queries.DeviceCreateParams
|
type DeviceCreateParams = models.DeviceSetter
|
||||||
|
|
||||||
func (api *API) DevicesCreate(ctx context.Context, params DeviceCreateParams) (queries.Device, error) {
|
func (api *API) DevicesCreate(ctx context.Context, params *DeviceCreateParams) (*models.Device, error) {
|
||||||
ctx, span := tracer.Start(ctx, "*API.DevicesCreate")
|
ctx, span := tracer.Start(ctx, "*API.DevicesCreate")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
return api.queries.DeviceCreate(ctx, params)
|
|
||||||
|
device, err := models.Devices.Insert(ctx, api.exec, params)
|
||||||
|
if err != nil {
|
||||||
|
var sqliteErr sqlite3.Error
|
||||||
|
if errors.As(err, &sqliteErr) {
|
||||||
|
if sqliteErr.Code == sqlite3.ErrConstraint {
|
||||||
|
return nil, errs.Wrapw(sqliteErr, "device already exists", "params", params).Code(409)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errs.Wrapw(err, "failed to create device", "params", params)
|
||||||
|
}
|
||||||
|
return device, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,74 +3,79 @@ package api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/tigorlazuardi/redmage/db/queries"
|
"github.com/stephenafamo/bob"
|
||||||
|
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||||
|
"github.com/stephenafamo/bob/dialect/sqlite/dialect"
|
||||||
|
"github.com/stephenafamo/bob/dialect/sqlite/sm"
|
||||||
|
"github.com/tigorlazuardi/redmage/models"
|
||||||
"github.com/tigorlazuardi/redmage/pkg/errs"
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DevicesListParams struct {
|
type DevicesListParams struct {
|
||||||
All bool
|
All bool
|
||||||
Query string
|
Q string
|
||||||
Limit int64
|
Limit int64
|
||||||
Offset int64
|
Offset int64
|
||||||
|
OrderBy string
|
||||||
|
Sort string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dlp DevicesListParams) Query() (expr []bob.Mod[*dialect.SelectQuery]) {
|
||||||
|
expr = append(expr, dlp.CountQuery()...)
|
||||||
|
if dlp.All {
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
|
if dlp.Limit > 0 {
|
||||||
|
expr = append(expr, sm.Limit(dlp.Limit))
|
||||||
|
}
|
||||||
|
|
||||||
|
if dlp.Offset > 0 {
|
||||||
|
expr = append(expr, sm.Offset(dlp.Offset))
|
||||||
|
}
|
||||||
|
|
||||||
|
if dlp.OrderBy != "" {
|
||||||
|
order := sm.OrderBy(sqlite.Quote(dlp.OrderBy))
|
||||||
|
if dlp.Sort == "desc" {
|
||||||
|
expr = append(expr, order.Desc())
|
||||||
|
} else {
|
||||||
|
expr = append(expr, order.Asc())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dlp DevicesListParams) CountQuery() (expr []bob.Mod[*dialect.SelectQuery]) {
|
||||||
|
if dlp.Q != "" {
|
||||||
|
arg := sqlite.Arg("%" + dlp.Q + "%")
|
||||||
|
expr = append(expr,
|
||||||
|
sm.Where(
|
||||||
|
models.DeviceColumns.Name.Like(arg).Or(models.DeviceColumns.Slug.Like(arg)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
type DevicesListResult struct {
|
type DevicesListResult struct {
|
||||||
Devices []queries.Device `json:"devices"`
|
Devices models.DeviceSlice `json:"devices"`
|
||||||
Total int64 `json:"total"`
|
Total int64 `json:"total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) DevicesList(ctx context.Context, params DevicesListParams) (result DevicesListResult, err error) {
|
func (api *API) DevicesList(ctx context.Context, params DevicesListParams) (result DevicesListResult, err error) {
|
||||||
ctx, span := tracer.Start(ctx, "*API.DevicesList")
|
ctx, span := tracer.Start(ctx, "*API.DevicesList")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
q := params.Query
|
result.Devices, err = models.Devices.Query(ctx, api.exec, params.Query()...).All()
|
||||||
|
|
||||||
if params.All {
|
|
||||||
result.Devices, err = api.queries.DeviceGetAll(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return result, errs.Wrapw(err, "failed to get all devices", "params", params)
|
|
||||||
}
|
|
||||||
result.Total, err = api.queries.DeviceCount(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return result, errs.Wrapw(err, "failed to count all devices", "params", params)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if q != "" {
|
|
||||||
like := "%" + q + "%"
|
|
||||||
result.Devices, err = api.queries.DeviceSearch(ctx, queries.DeviceSearchParams{
|
|
||||||
Name: like,
|
|
||||||
Slug: like,
|
|
||||||
Limit: params.Limit,
|
|
||||||
Offset: params.Offset,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return result, errs.Wrapw(err, "failed to search device", "params", params)
|
|
||||||
}
|
|
||||||
result.Total, err = api.queries.DeviceSearchCount(ctx, queries.DeviceSearchCountParams{
|
|
||||||
Name: like,
|
|
||||||
Slug: like,
|
|
||||||
Limit: params.Limit,
|
|
||||||
Offset: params.Offset,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return result, errs.Wrapw(err, "failed to count device search", "params", params)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Devices, err = api.queries.DeviceList(ctx, queries.DeviceListParams{
|
|
||||||
Limit: params.Limit,
|
|
||||||
Offset: params.Offset,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, errs.Wrapw(err, "failed to list device", "params", params)
|
return result, errs.Wrapw(err, "failed to query devices", "params", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Total, err = api.queries.DeviceCount(ctx)
|
result.Total, err = models.Devices.Query(ctx, api.exec, params.CountQuery()...).Count()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, errs.Wrapw(err, "failed to count all devices", "params", params)
|
return result, errs.Wrapw(err, "failed to count devices", "params", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
28
api/devices_update.go
Normal file
28
api/devices_update.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/tigorlazuardi/redmage/models"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *API) DevicesUpdate(ctx context.Context, id int, update *models.DeviceSetter) (err error) {
|
||||||
|
ctx, span := tracer.Start(ctx, "*API.DevicesUpdate")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
err = models.Devices.Update(ctx, api.exec, update, &models.Device{ID: int32(id)})
|
||||||
|
if err != nil {
|
||||||
|
var sqliteErr sqlite3.Error
|
||||||
|
if errors.As(err, &sqliteErr) {
|
||||||
|
if sqliteErr.Code == sqlite3.ErrNo(sqlite3.ErrConstraintUnique) {
|
||||||
|
return errs.Wrapw(err, "a device with the same slug id already exists").Code(409)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errs.Wrapw(err, "failed to update device", "id", id, "values", update)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
|
@ -3,13 +3,30 @@ package errs
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
func FindCodeOrDefault(err error, def int) int {
|
func FindCodeOrDefault(err error, def int) int {
|
||||||
for unwrap := errors.Unwrap(err); unwrap != nil; err = unwrap {
|
unwrap := errors.Unwrap(err)
|
||||||
|
for unwrap != nil {
|
||||||
if coder, ok := err.(interface{ GetCode() int }); ok {
|
if coder, ok := err.(interface{ GetCode() int }); ok {
|
||||||
code := coder.GetCode()
|
code := coder.GetCode()
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
def = code
|
return code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unwrap = errors.Unwrap(unwrap)
|
||||||
|
}
|
||||||
|
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindMessage(err error) string {
|
||||||
|
unwrap := errors.Unwrap(err)
|
||||||
|
for unwrap != nil {
|
||||||
|
if messager, ok := err.(interface{ GetMessage() string }); ok {
|
||||||
|
message := messager.GetMessage()
|
||||||
|
if message != "" {
|
||||||
|
return message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return def
|
|
||||||
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
|
13
rest/devices/create.http
Normal file
13
rest/devices/create.http
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
POST http://localhost:8080/api/v1/devices HTTP/1.1
|
||||||
|
Host: localhost:8080
|
||||||
|
Content-Type: application/json
|
||||||
|
Content-Length: 155
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Laptop",
|
||||||
|
"slug": "laptop",
|
||||||
|
"resolution_x": 1920,
|
||||||
|
"resolution_y": 1080,
|
||||||
|
"nsfw": 1,
|
||||||
|
"aspect_ratio_tolerance": 0.2
|
||||||
|
}
|
1
rest/devices/list.http
Normal file
1
rest/devices/list.http
Normal file
|
@ -0,0 +1 @@
|
||||||
|
GET http://localhost:8080/api/v1/devices HTTP/1.1
|
9
rest/devices/update.http
Normal file
9
rest/devices/update.http
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
PATCH http://localhost:8080/api/v1/devices/1 HTTP/1.1
|
||||||
|
Host: localhost:8080
|
||||||
|
Content-Type: application/json
|
||||||
|
Content-Length: 55
|
||||||
|
|
||||||
|
{
|
||||||
|
"aspect_ratio_tolerance": 0.2,
|
||||||
|
"nsfw": 1
|
||||||
|
}
|
|
@ -5,8 +5,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"github.com/tigorlazuardi/redmage/api"
|
"github.com/aarondl/opt/omit"
|
||||||
|
"github.com/tigorlazuardi/redmage/models"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
"github.com/tigorlazuardi/redmage/pkg/log"
|
"github.com/tigorlazuardi/redmage/pkg/log"
|
||||||
"github.com/tigorlazuardi/redmage/pkg/telemetry"
|
"github.com/tigorlazuardi/redmage/pkg/telemetry"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +19,7 @@ func (routes *Routes) APIDeviceCreate(rw http.ResponseWriter, r *http.Request) {
|
||||||
ctx, span := tracer.Start(r.Context(), "*Routes.APIDeviceCreate")
|
ctx, span := tracer.Start(r.Context(), "*Routes.APIDeviceCreate")
|
||||||
defer func() { telemetry.EndWithStatus(span, err) }()
|
defer func() { telemetry.EndWithStatus(span, err) }()
|
||||||
|
|
||||||
var body api.DeviceCreateParams
|
var body models.Device
|
||||||
|
|
||||||
if err = json.NewDecoder(r.Body).Decode(&body); err != nil {
|
if err = json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
log.New(ctx).Err(err).Error("failed to decode json body")
|
log.New(ctx).Err(err).Error("failed to decode json body")
|
||||||
|
@ -25,37 +28,58 @@ func (routes *Routes) APIDeviceCreate(rw http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = validateDeviceCreateParams(body); err != nil {
|
if err = validateCreateDevice(body); err != nil {
|
||||||
rw.WriteHeader(http.StatusBadRequest)
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
_ = json.NewEncoder(rw).Encode(map[string]string{"error": err.Error()})
|
_ = json.NewEncoder(rw).Encode(map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
device, err := routes.API.DevicesCreate(ctx, body)
|
device, err := routes.API.DevicesCreate(ctx, &models.DeviceSetter{
|
||||||
|
Slug: omit.From(body.Slug),
|
||||||
|
Name: omit.From(body.Name),
|
||||||
|
ResolutionX: omit.From(body.ResolutionX),
|
||||||
|
ResolutionY: omit.From(body.ResolutionY),
|
||||||
|
AspectRatioTolerance: omit.From(body.AspectRatioTolerance),
|
||||||
|
MinX: omit.From(body.MinX),
|
||||||
|
MinY: omit.From(body.MinY),
|
||||||
|
MaxX: omit.From(body.MaxX),
|
||||||
|
MaxY: omit.From(body.MaxY),
|
||||||
|
NSFW: omit.From(body.NSFW),
|
||||||
|
WindowsWallpaperMode: omit.From(body.WindowsWallpaperMode),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rw.WriteHeader(http.StatusInternalServerError)
|
rw.WriteHeader(errs.FindCodeOrDefault(err, http.StatusInternalServerError))
|
||||||
_ = json.NewEncoder(rw).Encode(map[string]string{"error": err.Error()})
|
_ = json.NewEncoder(rw).Encode(map[string]string{"error": errs.FindMessage(err)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rw.WriteHeader(http.StatusCreated)
|
||||||
if err := json.NewEncoder(rw).Encode(device); err != nil {
|
if err := json.NewEncoder(rw).Encode(device); err != nil {
|
||||||
log.New(ctx).Err(err).Error("failed to marshal json api devices")
|
log.New(ctx).Err(err).Error("failed to marshal json api devices")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateDeviceCreateParams(params api.DeviceCreateParams) error {
|
var slugRegex = regexp.MustCompile(`^[a-z0-9-]+$`)
|
||||||
|
|
||||||
|
func validateCreateDevice(params models.Device) error {
|
||||||
if params.Name == "" {
|
if params.Name == "" {
|
||||||
return errors.New("name is required")
|
return errors.New("name is required")
|
||||||
}
|
}
|
||||||
if params.Slug == "" {
|
if params.Slug == "" {
|
||||||
return errors.New("slug is required")
|
return errors.New("slug is required")
|
||||||
}
|
}
|
||||||
|
if !slugRegex.MatchString(params.Slug) {
|
||||||
|
return errors.New("slug must be lowercase alphanumeric with dash. eg: my-awesome-laptop")
|
||||||
|
}
|
||||||
if params.ResolutionX < 1 {
|
if params.ResolutionX < 1 {
|
||||||
return errors.New("device width resolution is required")
|
return errors.New("device width resolution is required")
|
||||||
}
|
}
|
||||||
if params.ResolutionY < 1 {
|
if params.ResolutionY < 1 {
|
||||||
return errors.New("device height resolution is required")
|
return errors.New("device height resolution is required")
|
||||||
}
|
}
|
||||||
|
if params.AspectRatioTolerance < 0 {
|
||||||
|
return errors.New("aspect ratio tolerance cannot be negative value")
|
||||||
|
}
|
||||||
if params.MaxX < 0 {
|
if params.MaxX < 0 {
|
||||||
params.MaxX = 0
|
params.MaxX = 0
|
||||||
}
|
}
|
||||||
|
@ -68,5 +92,17 @@ func validateDeviceCreateParams(params api.DeviceCreateParams) error {
|
||||||
if params.MinY < 0 {
|
if params.MinY < 0 {
|
||||||
params.MinY = 0
|
params.MinY = 0
|
||||||
}
|
}
|
||||||
|
if params.NSFW < 0 {
|
||||||
|
params.NSFW = 0
|
||||||
|
}
|
||||||
|
if params.NSFW > 1 {
|
||||||
|
params.NSFW = 1
|
||||||
|
}
|
||||||
|
if params.WindowsWallpaperMode < 0 {
|
||||||
|
params.WindowsWallpaperMode = 0
|
||||||
|
}
|
||||||
|
if params.WindowsWallpaperMode > 1 {
|
||||||
|
params.WindowsWallpaperMode = 1
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,17 @@ func parseApiDeviceListQueries(req *http.Request) (params api.DevicesListParams)
|
||||||
params.All, _ = strconv.ParseBool(req.FormValue("all"))
|
params.All, _ = strconv.ParseBool(req.FormValue("all"))
|
||||||
params.Offset, _ = strconv.ParseInt(req.FormValue("offset"), 10, 64)
|
params.Offset, _ = strconv.ParseInt(req.FormValue("offset"), 10, 64)
|
||||||
params.Limit, _ = strconv.ParseInt(req.FormValue("limit"), 10, 64)
|
params.Limit, _ = strconv.ParseInt(req.FormValue("limit"), 10, 64)
|
||||||
params.Query = req.FormValue("q")
|
params.Q = req.FormValue("q")
|
||||||
|
params.OrderBy = req.FormValue("order")
|
||||||
|
params.Sort = req.FormValue("sort")
|
||||||
|
|
||||||
if params.Limit < 1 {
|
if params.Limit < 1 {
|
||||||
params.Limit = 10
|
params.Limit = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if params.OrderBy == "" {
|
||||||
|
params.OrderBy = "name"
|
||||||
|
}
|
||||||
|
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
70
server/routes/device_update.go
Normal file
70
server/routes/device_update.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/aarondl/opt/omit"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/tigorlazuardi/redmage/models"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/errs"
|
||||||
|
"github.com/tigorlazuardi/redmage/pkg/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type deviceUpdate struct {
|
||||||
|
models.Device
|
||||||
|
|
||||||
|
MinX *int32 `json:"min_x"`
|
||||||
|
MinY *int32 `json:"min_y"`
|
||||||
|
MaxX *int32 `json:"max_x"`
|
||||||
|
MaxY *int32 `json:"max_y"`
|
||||||
|
NSFW *int32 `json:"nsfw"`
|
||||||
|
WindowsWallpaperMode *int32 `json:"windows_wallpaper_mode"`
|
||||||
|
AspectRatioTolerance *float64 `json:"aspect_ratio_tolerance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (routes *Routes) APIDeviceUpdate(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
var err error
|
||||||
|
ctx, span := tracer.Start(r.Context(), "*Routes.APIDeviceUpdate")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
id, err := strconv.Atoi(chi.URLParam(r, "id"))
|
||||||
|
if err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to parse id")
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
_ = json.NewEncoder(rw).Encode(map[string]string{"error": fmt.Sprintf("bad id: %s", err)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var body deviceUpdate
|
||||||
|
|
||||||
|
if err = json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
log.New(ctx).Err(err).Error("failed to decode json body")
|
||||||
|
rw.WriteHeader(http.StatusBadRequest)
|
||||||
|
_ = json.NewEncoder(rw).Encode(map[string]string{"error": fmt.Sprintf("cannot decode json body: %s", err)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = routes.API.DevicesUpdate(ctx, id, &models.DeviceSetter{
|
||||||
|
Slug: omit.FromCond(body.Slug, body.Slug != ""),
|
||||||
|
Name: omit.FromCond(body.Name, body.Name != ""),
|
||||||
|
ResolutionX: omit.FromCond(body.ResolutionX, body.ResolutionX != 0),
|
||||||
|
ResolutionY: omit.FromCond(body.ResolutionY, body.ResolutionY != 0),
|
||||||
|
AspectRatioTolerance: omit.FromPtr(body.AspectRatioTolerance),
|
||||||
|
MinX: omit.FromPtr(body.MinX),
|
||||||
|
MinY: omit.FromPtr(body.MinY),
|
||||||
|
MaxX: omit.FromPtr(body.MaxX),
|
||||||
|
MaxY: omit.FromPtr(body.MaxY),
|
||||||
|
NSFW: omit.FromPtr(body.NSFW),
|
||||||
|
WindowsWallpaperMode: omit.FromPtr(body.WindowsWallpaperMode),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
rw.WriteHeader(errs.FindCodeOrDefault(err, http.StatusInternalServerError))
|
||||||
|
_ = json.NewEncoder(rw).Encode(map[string]string{"error": errs.FindMessage(err)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = json.NewEncoder(rw).Encode(map[string]string{"message": "ok"})
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ type Routes struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routes *Routes) Register(router chi.Router) {
|
func (routes *Routes) Register(router chi.Router) {
|
||||||
|
router.Use(chimiddleware.Compress(5, "text/html", "text/css", "application/javascript", "application/json"))
|
||||||
|
|
||||||
router.HandleFunc("/ping", routes.HealthCheck)
|
router.HandleFunc("/ping", routes.HealthCheck)
|
||||||
router.HandleFunc("/health", routes.HealthCheck)
|
router.HandleFunc("/health", routes.HealthCheck)
|
||||||
if routes.Config.Bool("http.hotreload") {
|
if routes.Config.Bool("http.hotreload") {
|
||||||
|
@ -37,10 +39,10 @@ func (routes *Routes) registerV1APIRoutes(router chi.Router) {
|
||||||
router.Get("/subreddits", routes.SubredditsListAPI)
|
router.Get("/subreddits", routes.SubredditsListAPI)
|
||||||
router.Get("/devices", routes.APIDeviceList)
|
router.Get("/devices", routes.APIDeviceList)
|
||||||
router.Post("/devices", routes.APIDeviceCreate)
|
router.Post("/devices", routes.APIDeviceCreate)
|
||||||
|
router.Patch("/devices/{id}", routes.APIDeviceUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routes *Routes) registerWWWRoutes(router chi.Router) {
|
func (routes *Routes) registerWWWRoutes(router chi.Router) {
|
||||||
router.Use(chimiddleware.Compress(5, "text/html", "text/css", "application/javascript"))
|
|
||||||
router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir))))
|
router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir))))
|
||||||
|
|
||||||
router.Group(func(r chi.Router) {
|
router.Group(func(r chi.Router) {
|
||||||
|
|
Loading…
Reference in a new issue