master
serr 2025-04-05 18:31:48 +03:00
parent 5374e47fb5
commit e143107de0
1 changed files with 37 additions and 37 deletions

74
main.go
View File

@ -21,88 +21,88 @@ sudo systemctl start server.service
*/ */
// App представляет основное состояние приложения // App представляет основное состояние приложения
type App struct { type app struct {
Templates *template.Template // Шаблоны страниц templates *template.Template // Шаблоны страниц
Config *config.Config // Конфиг config *config.Config // Конфиг
StartTime int64 // Время запуска startTime int64 // Время запуска
Cache *cache.Cache // Кэш (отрендеренные странички) cache *cache.Cache // Кэш (отрендеренные странички)
} }
func main() { func main() {
var app *App var app *app
var err error var err error
// Инициализация приложения // Инициализация приложения
if app, err = AppInit("config.json"); err != nil { if app, err = appInit("config.json"); err != nil {
log.Fatal(err) log.Fatal(err)
} }
// Настройка маршрутов и запуск // Настройка маршрутов и запуск
if app.SetupRouterAndRun() != nil { if app.setupRouterAndRun() != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
// Запускает сервер на указанном IP и порту // Запускает сервер на указанном IP и порту
func RunServer(ip, port string, router http.Handler) { func runServer(ip, port string, router http.Handler) {
addr := ip + port addr := ip + port
log.Println("Run on", addr) log.Println("Run on", addr)
log.Fatal(http.ListenAndServe(addr, router)) log.Fatal(http.ListenAndServe(addr, router))
} }
// Инициализирует приложение // Инициализирует приложение
func AppInit(configPath string) (*App, error) { func appInit(configPath string) (*app, error) {
a := &App{ a := &app{
StartTime: time.Now().Unix(), startTime: time.Now().Unix(),
Config: config.Init(), config: config.Init(),
Cache: cache.Init(), cache: cache.Init(),
} }
// Загрузка конфига // Загрузка конфига
if err := a.Config.Load(configPath); err != nil { if err := a.config.Load(configPath); err != nil {
return nil, err return nil, err
} }
// Загрузка шаблонов // Загрузка шаблонов
if err := a.LoadTemplates(a.Config.TemplatesPath, a.Config.TemplatesExt); err != nil { if err := a.loadTemplates(a.config.TemplatesPath, a.config.TemplatesExt); err != nil {
log.Fatal(err) log.Fatal(err)
} }
return a, nil return a, nil
} }
func (a *App) SetupRouterAndRun() error { func (a *app) setupRouterAndRun() error {
// Настройка маршрутов // Настройка маршрутов
router := a.SetupRouter() router := a.setupRouter()
// Запуск сервера // Запуск сервера
if ok, err := tools.IsIPInUse(a.Config.ServerIP); err != nil { if ok, err := tools.IsIPInUse(a.config.ServerIP); err != nil {
return err return err
} else if ok { } else if ok {
RunServer(a.Config.ServerIP, a.Config.Port, router) runServer(a.config.ServerIP, a.config.Port, router)
} else { } else {
RunServer(a.Config.LocalIP, a.Config.Port, router) runServer(a.config.LocalIP, a.config.Port, router)
} }
return nil return nil
} }
// Настраивает маршруты // Настраивает маршруты
func (a *App) SetupRouter() *http.ServeMux { func (a *app) setupRouter() *http.ServeMux {
router := http.NewServeMux() router := http.NewServeMux()
// Обработка статических файлов с кэшированием // Обработка статических файлов с кэшированием
router.Handle(a.Config.AssetsPath, a.StaticHandler()) router.Handle(a.config.AssetsPath, a.staticHandler())
// Обработка главной страницы // Обработка главной страницы
router.Handle("/", a.MainPageHandler()) router.Handle("/", a.mainPageHandler())
return router return router
} }
// Обработчик статических файлов с кэшированием // Обработчик статических файлов с кэшированием
func (a *App) StaticHandler() http.HandlerFunc { func (a *app) staticHandler() http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Cache-Control", "public, max-age=31536000, immutable") w.Header().Add("Cache-Control", "public, max-age=31536000, immutable")
// Здесь используется встроенный файловый сервер Go (http.FileServer), который: // Здесь используется встроенный файловый сервер Go (http.FileServer), который:
@ -114,32 +114,32 @@ func (a *App) StaticHandler() http.HandlerFunc {
} }
// Обработчик главной страницы // Обработчик главной страницы
func (a *App) MainPageHandler() http.HandlerFunc { func (a *app) mainPageHandler() http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error var err error
tmplName := "main" + a.Config.TemplatesExt tmplName := "main" + a.config.TemplatesExt
// Страничка рендерится только если ее нет в кэше // Страничка рендерится только если ее нет в кэше
pageData, ok := a.Cache.Get(tmplName) pageData, ok := a.cache.Get(tmplName)
if !ok { if !ok {
context := map[string]any{ context := map[string]any{
"version": a.StartTime, "version": a.startTime,
"renderingTimestamp": time.Now().Unix(), "renderingTimestamp": time.Now().Unix(),
} }
pageData, err = a.RenderPage(tmplName, context) pageData, err = a.renderPage(tmplName, context)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
a.Cache.Set(tmplName, pageData) a.cache.Set(tmplName, pageData)
} }
a.SendPage(w, pageData.([]byte)) a.sendPage(w, pageData.([]byte))
}) })
} }
// Загрузка шаблонов // Загрузка шаблонов
func (a *App) LoadTemplates(templatesPath string, ext string) error { func (a *app) loadTemplates(templatesPath string, ext string) error {
tmpls := template.New("") tmpls := template.New("")
err := filepath.Walk(templatesPath, func(path string, f os.FileInfo, err error) error { err := filepath.Walk(templatesPath, func(path string, f os.FileInfo, err error) error {
@ -159,15 +159,15 @@ func (a *App) LoadTemplates(templatesPath string, ext string) error {
return err return err
} }
a.Templates = tmpls a.templates = tmpls
return nil return nil
} }
// Рендерит шаблон в срез байт // Рендерит шаблон в срез байт
func (a *App) RenderPage(tmplName string, context any) ([]byte, error) { func (a *app) renderPage(tmplName string, context any) ([]byte, error) {
var pageData bytes.Buffer var pageData bytes.Buffer
if err := a.Templates.ExecuteTemplate(&pageData, tmplName, context); err != nil { if err := a.templates.ExecuteTemplate(&pageData, tmplName, context); err != nil {
return nil, err return nil, err
} }
@ -175,7 +175,7 @@ func (a *App) RenderPage(tmplName string, context any) ([]byte, error) {
} }
// Отправляет страницу // Отправляет страницу
func (a *App) SendPage(w http.ResponseWriter, data []byte) { func (a *app) sendPage(w http.ResponseWriter, data []byte) {
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write(data) w.Write(data)