83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
|
package httpsrv
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"log/slog"
|
||
|
"net/http"
|
||
|
"recipes/internal/config"
|
||
|
"recipes/internal/http-server/handlers/recipe"
|
||
|
recipeimage "recipes/internal/http-server/handlers/recipeImage"
|
||
|
"recipes/internal/http-server/handlers/recipes"
|
||
|
recipes_by_category "recipes/internal/http-server/handlers/recipesByCategory"
|
||
|
mwLogger "recipes/internal/http-server/middleware/logger"
|
||
|
"recipes/internal/lib/logger/sl"
|
||
|
"time"
|
||
|
|
||
|
"github.com/go-chi/chi/v5"
|
||
|
"github.com/go-chi/chi/v5/middleware"
|
||
|
)
|
||
|
|
||
|
type App struct {
|
||
|
log *slog.Logger
|
||
|
router *chi.Mux
|
||
|
srv *http.Server
|
||
|
}
|
||
|
|
||
|
type Storage interface {
|
||
|
recipe.RecipeProvider
|
||
|
recipes.RecipesProvider
|
||
|
recipes_by_category.RecipesProvider
|
||
|
}
|
||
|
|
||
|
type MediaStorage interface {
|
||
|
recipeimage.ImageProvider
|
||
|
}
|
||
|
|
||
|
func New(log *slog.Logger, cfg *config.HTTPServerConfig, storage Storage, mediaStorage MediaStorage) *App {
|
||
|
// init router
|
||
|
router := chi.NewRouter()
|
||
|
// middlewares
|
||
|
router.Use(middleware.RequestID)
|
||
|
router.Use(mwLogger.New(log))
|
||
|
router.Use(middleware.Recoverer)
|
||
|
// routes
|
||
|
router.Get("/recipe", recipe.New(log, storage))
|
||
|
router.Get("/recipes_page", recipes.New(log, storage))
|
||
|
router.Get("/recipes_by_category", recipes_by_category.New(log, storage))
|
||
|
router.Get("/recipe_img", recipeimage.New(log, mediaStorage))
|
||
|
// server config
|
||
|
srv := &http.Server{
|
||
|
Addr: cfg.Address,
|
||
|
Handler: router,
|
||
|
ReadTimeout: cfg.Timeout,
|
||
|
WriteTimeout: cfg.Timeout,
|
||
|
IdleTimeout: cfg.IdleTimeout,
|
||
|
}
|
||
|
|
||
|
return &App{
|
||
|
log: log,
|
||
|
router: router,
|
||
|
srv: srv,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MustRun starts http server or panic in case of error. Blocking function.
|
||
|
func (app *App) MustRun() {
|
||
|
const op = "app.httpSrv.Stop"
|
||
|
if err := app.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||
|
app.log.Error("failed to start server", sl.Err(err))
|
||
|
panic(err)
|
||
|
}
|
||
|
app.log.Info("HTTP server stopped")
|
||
|
}
|
||
|
|
||
|
func (app *App) Stop() {
|
||
|
const op = "app.httpSrv.Stop"
|
||
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||
|
err := app.srv.Shutdown(shutdownCtx)
|
||
|
if err != nil {
|
||
|
app.log.Error("failed to stop server", sl.Err(err))
|
||
|
}
|
||
|
shutdownCancel()
|
||
|
}
|