package fiber
import (
"errors"
"html/template"
"strconv"
"time"
cache "git.dmitriygnatenko.ru/dima/go-common/cache/ttl_memory_cache"
"git.dmitriygnatenko.ru/dima/go-common/db"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/html/v2"
"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/repositories"
"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/auth"
"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/config"
"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/i18n"
)
const (
appName = "dmitriygnatenko"
templatesPath = "./../../internal/templates"
staticPath = "../../web"
metricsURI = "/metrics"
)
type ServiceProvider interface {
ConfigService() *config.Service
AuthService() *auth.Service
CacheService() *cache.Cache
TransactionManager() *db.TxManager
ArticleRepository() *repositories.ArticleRepository
TagRepository() *repositories.TagRepository
ArticleTagRepository() *repositories.ArticleTagRepository
UserRepository() *repositories.UserRepository
}
func Init(sp ServiceProvider) (*fiber.App, error) {
fiberApp := fiber.New(getConfig(sp))
initStatic(fiberApp)
initMiddleware(fiberApp, sp)
initMetrics(fiberApp, sp)
initPublicHandlers(fiberApp, sp)
initAdminHandlers(fiberApp, sp)
return fiberApp, nil
}
func getConfig(sp ServiceProvider) fiber.Config {
return fiber.Config{
AppName: appName,
DisableStartupMessage: true,
Views: getViewsEngine(sp),
ErrorHandler: getErrorHandler(),
}
}
func getViewsEngine(sp ServiceProvider) *html.Engine {
engine := html.New(templatesPath, ".html")
// nolint:gocritic
engine.AddFunc("now", func() time.Time {
return time.Now()
})
// nolint:gosec
engine.AddFunc("noescape", func(str string) template.HTML {
return template.HTML(str)
})
engine.AddFunc("gridsep", func(i, l int) bool {
i++
return i%3 == 0 && i != l
})
engine.AddFunc("version", func() string {
return strconv.FormatUint(uint64(sp.ConfigService().StaticVersion()), 10)
})
return engine
}
func getErrorHandler() fiber.ErrorHandler {
return func(fctx *fiber.Ctx, err error) error {
lang := i18n.Language(fctx)
errCode := fiber.StatusInternalServerError
var e *fiber.Error
if errors.As(err, &e) {
errCode = e.Code
}
var renderData fiber.Map
if errCode == fiber.StatusNotFound {
renderData = fiber.Map{
"pageTitle": i18n.T(lang, "page_not_found_err_title"),
"code": fiber.StatusNotFound,
"text": i18n.T(lang, "page_not_found_err_desc"),
}
} else {
renderData = fiber.Map{
"pageTitle": i18n.T(lang, "internal_err_title"),
"code": fiber.StatusInternalServerError,
"text": i18n.T(lang, "internal_err_desc"),
}
}
renderData["headTitle"] = i18n.T(lang, "head_title")
return fctx.Render("error", renderData, "_layout")
}
}