recipes2/internal/http-server/handlers/recipes/recipes.go

72 lines
1.8 KiB
Go
Raw Normal View History

2024-01-23 17:28:59 +02:00
package recipes
import (
"context"
"log/slog"
"net/http"
"recipes/internal/domain/models"
resp "recipes/internal/lib/api/response"
"recipes/internal/lib/logger/sl"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/render"
"github.com/go-playground/validator/v10"
)
type Request struct {
Page uint `json:"page" validate:"required,gt=0"`
}
type Response struct {
resp.Response
Recipes []models.Recipe `json:"recipes"`
}
2024-01-28 10:37:18 +02:00
//go:generate go run github.com/vektra/mockery/v2@v2.40.1 --name=RecipesProvider
type RecipesProvider interface {
2024-01-23 17:28:59 +02:00
GetRecipes(ctx context.Context, offset, limit int) ([]models.Recipe, error)
}
2024-01-29 14:01:58 +02:00
const GetRecipesLimit int = 16
2024-01-23 17:28:59 +02:00
func New(log *slog.Logger, recipesProvider RecipesProvider) http.HandlerFunc {
2024-01-23 17:28:59 +02:00
return func(w http.ResponseWriter, r *http.Request) {
const op = "http-server.handlers.recipes.New"
2024-01-27 20:42:23 +02:00
log := log.With(
2024-01-23 17:28:59 +02:00
slog.String("op", op),
slog.String("request_id", middleware.GetReqID(r.Context())),
)
var req Request
// decode request
err := render.DecodeJSON(r.Body, &req)
if err != nil {
log.Error("failed to decode request body", sl.Err(err))
render.JSON(w, r, resp.Error("failed to decode request"))
return
}
log.Debug("request body decoded", slog.Any("request", req))
// validate request
if err := validator.New().Struct(req); err != nil {
validateErr := err.(validator.ValidationErrors)
log.Error("invalid request", sl.Err(err))
render.JSON(w, r, resp.ValidationError(validateErr))
return
}
// get from storage
2024-01-29 14:01:58 +02:00
recipes, err := recipesProvider.GetRecipes(r.Context(), GetRecipesLimit*(int(req.Page)-1), GetRecipesLimit)
2024-01-23 17:28:59 +02:00
if err != nil {
log.Error("failed to get recipes from storage", sl.Err(err))
render.JSON(w, r, resp.Error("failed to get recipes"))
return
}
// return
render.JSON(w, r, Response{
Response: resp.OK(),
Recipes: recipes,
})
}
}