fiber.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package fiber
  2. import (
  3. "errors"
  4. "html/template"
  5. "strconv"
  6. "time"
  7. cache "git.dmitriygnatenko.ru/dima/go-common/cache/ttl_memory_cache"
  8. "git.dmitriygnatenko.ru/dima/go-common/db"
  9. "github.com/gofiber/fiber/v2"
  10. "github.com/gofiber/fiber/v2/middleware/cors"
  11. "github.com/gofiber/fiber/v2/middleware/recover"
  12. "github.com/gofiber/template/html/v2"
  13. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/middleware/language"
  14. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/repositories"
  15. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/auth"
  16. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/config"
  17. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/i18n"
  18. )
  19. const (
  20. appName = "dmitriygnatenko"
  21. templatesPath = "./../../internal/templates"
  22. staticPath = "../../web"
  23. metricsURI = "/metrics"
  24. )
  25. type ServiceProvider interface {
  26. ConfigService() *config.Service
  27. AuthService() *auth.Service
  28. CacheService() *cache.Cache
  29. TransactionManager() *db.TxManager
  30. ArticleRepository() *repositories.ArticleRepository
  31. TagRepository() *repositories.TagRepository
  32. ArticleTagRepository() *repositories.ArticleTagRepository
  33. UserRepository() *repositories.UserRepository
  34. }
  35. func Init(sp ServiceProvider) (*fiber.App, error) {
  36. fiberApp := fiber.New(getConfig(sp))
  37. // Configure web root
  38. fiberApp.Static("/", staticPath)
  39. // Configure CORS middleware
  40. fiberApp.Use(cors.New(getCORSConfig(sp)))
  41. // Configure recover middleware
  42. fiberApp.Use(recover.New())
  43. // Configure language middleware
  44. fiberApp.Use(language.New())
  45. // Metrics
  46. addMetrics(fiberApp, sp)
  47. // Public handlers
  48. addPublicHandlers(fiberApp, sp)
  49. // Protected handlers
  50. addAdminHandlers(fiberApp, sp)
  51. return fiberApp, nil
  52. }
  53. func getConfig(sp ServiceProvider) fiber.Config {
  54. return fiber.Config{
  55. AppName: appName,
  56. DisableStartupMessage: true,
  57. Views: getViewsEngine(sp),
  58. ErrorHandler: getErrorHandler(),
  59. }
  60. }
  61. func getCORSConfig(sp ServiceProvider) cors.Config {
  62. return cors.Config{
  63. AllowOrigins: sp.ConfigService().CORSAllowOrigins(),
  64. AllowMethods: sp.ConfigService().CORSAllowMethods(),
  65. }
  66. }
  67. func getViewsEngine(sp ServiceProvider) *html.Engine {
  68. engine := html.New(templatesPath, ".html")
  69. // nolint:gocritic
  70. engine.AddFunc("now", func() time.Time {
  71. return time.Now()
  72. })
  73. // nolint:gosec
  74. engine.AddFunc("noescape", func(str string) template.HTML {
  75. return template.HTML(str)
  76. })
  77. engine.AddFunc("gridsep", func(i, l int) bool {
  78. i++
  79. return i%3 == 0 && i != l
  80. })
  81. engine.AddFunc("version", func() string {
  82. return strconv.FormatUint(uint64(sp.ConfigService().StaticVersion()), 10)
  83. })
  84. return engine
  85. }
  86. func getErrorHandler() fiber.ErrorHandler {
  87. return func(fctx *fiber.Ctx, err error) error {
  88. lang := i18n.Language(fctx)
  89. errCode := fiber.StatusInternalServerError
  90. var e *fiber.Error
  91. if errors.As(err, &e) {
  92. errCode = e.Code
  93. }
  94. var renderData fiber.Map
  95. if errCode == fiber.StatusNotFound {
  96. renderData = fiber.Map{
  97. "pageTitle": i18n.T(lang, "page_not_found_err_title"),
  98. "code": fiber.StatusNotFound,
  99. "text": i18n.T(lang, "page_not_found_err_desc"),
  100. }
  101. } else {
  102. renderData = fiber.Map{
  103. "pageTitle": i18n.T(lang, "internal_err_title"),
  104. "code": fiber.StatusInternalServerError,
  105. "text": i18n.T(lang, "internal_err_desc"),
  106. }
  107. }
  108. renderData["headTitle"] = i18n.T(lang, "head_title")
  109. return fctx.Render("error", renderData, "_layout")
  110. }
  111. }