2024-01-23 12:22:16 +02:00
|
|
|
package recipe
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"log/slog"
|
|
|
|
"net/http"
|
|
|
|
"recipes/internal/domain/models"
|
|
|
|
resp "recipes/internal/lib/api/response"
|
|
|
|
"recipes/internal/lib/logger/sl"
|
|
|
|
"recipes/internal/storage"
|
|
|
|
|
|
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
|
|
"github.com/go-chi/render"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Request struct {
|
|
|
|
RecipeId uint `json:"recipe_id" validate:"required"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Response struct {
|
|
|
|
resp.Response
|
|
|
|
Recipe models.Recipe `json:"recipe"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type RecipeProvider interface {
|
|
|
|
GetRecipe(ctx context.Context, r_id uint) (models.Recipe, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func New(log *slog.Logger, recipeProvider RecipeProvider) http.HandlerFunc {
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
const op = "http-server.handlers.recipe.New"
|
|
|
|
|
2024-01-27 20:42:23 +02:00
|
|
|
log := log.With(
|
2024-01-23 12:22:16 +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
|
|
|
|
recipe, err := recipeProvider.GetRecipe(r.Context(), req.RecipeId)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("failed to get recipe from storage", sl.Err(err))
|
|
|
|
if errors.Is(err, storage.ErrRecipeNotFound) {
|
|
|
|
render.JSON(w, r, resp.Error("recipe not found"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
render.JSON(w, r, resp.Error("failed to get recipe"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// render response
|
2024-01-23 17:28:59 +02:00
|
|
|
render.JSON(w, r, Response{
|
2024-01-23 12:22:16 +02:00
|
|
|
Response: resp.OK(),
|
|
|
|
Recipe: recipe,
|
2024-01-23 17:28:59 +02:00
|
|
|
})
|
2024-01-23 12:22:16 +02:00
|
|
|
}
|
|
|
|
}
|