package fiber
import (
"html/template"
"log"
"strconv"
"time"
"github.com/dmitriygnatenko/internal/interfaces"
"github.com/dmitriygnatenko/internal/services/handler"
adminHandler "github.com/dmitriygnatenko/internal/services/handler/admin"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/basicauth"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/monitor"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/template/html"
)
const (
appName = "dmitriygnatenko"
templatesPath = "./../../internal/templates"
staticPath = "../../web"
)
func Init(sp interfaces.IServiceProvider) (*fiber.App, error) {
fiberApp := fiber.New(getConfig(sp))
// Configure web root
fiberApp.Static("/", staticPath)
// Configure CORS middleware
fiberApp.Use(cors.New())
// Configure recover middleware
fiberApp.Use(recover.New())
// Configure handlers
fiberApp.Get("/", handler.MainPageHandler(sp))
fiberApp.Get("/tag/:tag", handler.TagHandler(sp))
fiberApp.Get("/article/:article", handler.ArticleHandler(sp))
// Admin
user := sp.GetEnvService().GetAdminUser()
password := sp.GetEnvService().GetAdminPassword()
if user != "" && password != "" {
admin := fiberApp.Group("/admin", basicauth.New(basicauth.Config{
Users: map[string]string{
user: password,
},
}))
admin.Get("/metrics", monitor.New(monitor.Config{}))
admin.Get("/", adminHandler.ArticleHandler(sp))
admin.All("/article/add", adminHandler.AddArticleHandler(sp))
admin.All("/article/edit/:id", adminHandler.EditArticleHandler(sp))
admin.All("/article/delete/:id", adminHandler.DeleteArticleHandler(sp))
admin.Get("/tag", adminHandler.TagHandler(sp))
admin.All("/tag/add", adminHandler.AddTagHandler(sp))
admin.All("/tag/edit/:id", adminHandler.EditTagHandler(sp))
admin.All("/tag/delete/:id", adminHandler.DeleteTagHandler(sp))
}
return fiberApp, nil
}
func getConfig(sp interfaces.IServiceProvider) fiber.Config {
return fiber.Config{
AppName: appName,
DisableStartupMessage: true,
Views: initEngine(sp.GetEnvService()),
ErrorHandler: initErrorHandler(sp),
}
}
func initEngine(env interfaces.IEnv) *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 env.GetStaticVersion()
})
engine.AddFunc("ga", func() bool {
return env.IsGAEnabled()
})
return engine
}
func initErrorHandler(sp interfaces.IServiceProvider) fiber.ErrorHandler {
return func(ctx *fiber.Ctx, err error) error {
errCode := fiber.StatusInternalServerError
errText := err.Error()
if e, ok := err.(*fiber.Error); ok {
errCode = e.Code
}
var renderData fiber.Map
if errCode == fiber.StatusNotFound {
renderData = fiber.Map{
"pageTitle": "Страница не найдена",
"code": fiber.StatusNotFound,
"text": "Запрашиваемая вами страница не найдена",
}
} else {
renderData = fiber.Map{
"pageTitle": "Внутренняя ошибка",
"code": fiber.StatusInternalServerError,
"text": "Внутренняя ошибка сервера, идем исправлять...",
}
if errText != "" {
sendErr := sp.GetMailerService().Send(
sp.GetEnvService().GetAdminEmail(),
"Ошибка на сайте dmitriygnatenko.ru",
"Код: "+strconv.Itoa(errCode)+"\r\n"+"Текст: "+errText,
)
if sendErr != nil {
log.Print(sendErr)
}
}
}
renderData["headTitle"] = "От слона к суслику - статьи про PHP, Go, алгоритмы"
return ctx.Render("error", renderData, "_layout")
}
}