facade
parent
b68851c862
commit
cb0358dbb4
50
main.go
50
main.go
|
@ -6,75 +6,57 @@ import (
|
|||
"main/mvc/controllers"
|
||||
"main/mvc/controllers/controllers_pages"
|
||||
"main/mvc/models"
|
||||
"main/mvc/models/models_pages"
|
||||
"main/tools"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
// Инициализация конфига
|
||||
if err := models.Cfg.Load("config.json"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var app *models.App
|
||||
|
||||
// Загрузка постов
|
||||
if err := models_pages.LoadPosts(models.Cfg.PostsDir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Инициализация приложения (обязательно после инициализации конфига)
|
||||
if err := models.InitApp(); err != nil {
|
||||
// Инициализация приложения
|
||||
if app, err = models.InitApp(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Добавление префикса в виде домена сервера к записям в лог
|
||||
log.SetPrefix(fmt.Sprintf("%s | ", models.Cfg.ServerDomain))
|
||||
log.SetPrefix(fmt.Sprintf("%s | ", app.Cfg.ServerDomain))
|
||||
|
||||
// Настройка маршрутов и запуск
|
||||
if setupRoutesAndRun() != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func setupRoutesAndRun() error {
|
||||
// Настройка маршрутов
|
||||
router := setupRoutes()
|
||||
router := setupRoutes(app)
|
||||
|
||||
// Запуск сервера
|
||||
if ok, err := tools.IsIPInUse(models.Cfg.ServerIP); err != nil {
|
||||
return err
|
||||
if ok, err := tools.IsIPInUse(app.Cfg.ServerIP); err != nil {
|
||||
log.Fatal(err)
|
||||
} else if ok {
|
||||
runServer(models.Cfg.ServerIP, models.Cfg.ServerPort, router)
|
||||
runServer(app.Cfg.ServerIP, app.Cfg.ServerPort, router)
|
||||
} else {
|
||||
runServer(models.Cfg.LocalIP, models.Cfg.LocalPort, router)
|
||||
runServer(app.Cfg.LocalIP, app.Cfg.LocalPort, router)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Настраивает маршруты
|
||||
func setupRoutes() *http.ServeMux {
|
||||
func setupRoutes(app *models.App) *http.ServeMux {
|
||||
router := http.NewServeMux()
|
||||
|
||||
// Цепочка обработчиков, которые сработают до отдачи страницы юзеру
|
||||
m := controllers.MiddlewaresChain
|
||||
|
||||
// Обработка статических файлов
|
||||
router.Handle(models.Cfg.AssetsDir, m(controllers.StaticHandler()))
|
||||
router.Handle(app.Cfg.AssetsDir, m(controllers.StaticHandler()))
|
||||
|
||||
// Главные странички
|
||||
{
|
||||
// Обработка главной страницы (русская версия)
|
||||
router.Handle("/ru/", m(controllers_pages.MainRuPageHandler()))
|
||||
router.Handle("/ru/", m(controllers_pages.MainRuPageHandler(app)))
|
||||
// Обработка главной страницы
|
||||
router.Handle("/", m(controllers_pages.MainPageHandler()))
|
||||
router.Handle("/", m(controllers_pages.MainPageHandler(app)))
|
||||
// Обработка страницы со списком постов
|
||||
router.Handle("/posts/", m(controllers_pages.PostsPageHandler()))
|
||||
router.Handle("/posts/", m(controllers_pages.PostsPageHandler(app)))
|
||||
// Обработка страничек постов
|
||||
for key := range models_pages.GetPosts() {
|
||||
for key := range app.Posts {
|
||||
postLink := string(key)
|
||||
router.Handle(postLink, m(controllers_pages.PostPageHandler()))
|
||||
router.Handle(postLink, m(controllers_pages.PostPageHandler(app)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
// Обработчик главной страницы
|
||||
func MainPageHandler() http.HandlerFunc {
|
||||
func MainPageHandler(app *models.App) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
|
@ -18,7 +18,7 @@ func MainPageHandler() http.HandlerFunc {
|
|||
// Количество запросов, обработанных сервером за 24ч
|
||||
if r.Method == "COUNT" {
|
||||
var count []byte
|
||||
if count, err = tools.GetJournalctlLogsCount("server", models.Cfg.ServerDomain, 24); err != nil {
|
||||
if count, err = tools.GetJournalctlLogsCount("server", app.Cfg.ServerDomain, 24); err != nil {
|
||||
log.Printf("%s", err.Error())
|
||||
}
|
||||
sendCount(w, count)
|
||||
|
@ -38,14 +38,14 @@ func MainPageHandler() http.HandlerFunc {
|
|||
}
|
||||
|
||||
// Страничка рендерится только если ее нет в кэше
|
||||
pageData, ok := models.PagesCache.Get(models_pages.MainPageTmplName)
|
||||
pageData, ok := app.PagesCache.Get(models_pages.MainPageTmplName)
|
||||
if !ok {
|
||||
pageData, err = models_pages.RenderMainPage(models.App.Templates, models.App.Version)
|
||||
pageData, err = models_pages.RenderMainPage(app.Templates, app.Version)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
models.PagesCache.Set(models_pages.MainPageTmplName, pageData)
|
||||
app.PagesCache.Set(models_pages.MainPageTmplName, pageData)
|
||||
}
|
||||
|
||||
sendMainPage(w, pageData.([]byte))
|
||||
|
|
|
@ -7,19 +7,19 @@ import (
|
|||
)
|
||||
|
||||
// Обработчик главной страницы
|
||||
func MainRuPageHandler() http.HandlerFunc {
|
||||
func MainRuPageHandler(app *models.App) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
|
||||
// Страничка рендерится только если ее нет в кэше
|
||||
pageData, ok := models.PagesCache.Get(models_pages.MainRuPageTmplName)
|
||||
pageData, ok := app.PagesCache.Get(models_pages.MainRuPageTmplName)
|
||||
if !ok {
|
||||
pageData, err = models_pages.RenderMainRuPage(models.App.Templates, models.App.Version)
|
||||
pageData, err = models_pages.RenderMainRuPage(app.Templates, app.Version)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
models.PagesCache.Set(models_pages.MainRuPageTmplName, pageData)
|
||||
app.PagesCache.Set(models_pages.MainRuPageTmplName, pageData)
|
||||
}
|
||||
|
||||
sendMainRuPage(w, pageData.([]byte))
|
||||
|
|
|
@ -7,24 +7,22 @@ import (
|
|||
)
|
||||
|
||||
// Обработчик главной страницы
|
||||
func PostPageHandler() http.HandlerFunc {
|
||||
func PostPageHandler(app *models.App) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
|
||||
posts := models_pages.GetPosts()
|
||||
|
||||
// Страничка рендерится только если ее нет в кэше
|
||||
pageData, ok := models.PagesCache.Get(models_pages.PostPageTmplName)
|
||||
pageData, ok := app.PagesCache.Get(models_pages.PostPageTmplName)
|
||||
if !ok {
|
||||
|
||||
post := posts[models_pages.PostLink(r.URL.Path)]
|
||||
post := app.Posts[models_pages.PostLink(r.URL.Path)]
|
||||
|
||||
pageData, err = models_pages.RenderPostPage(models.App.Templates, models.App.Version, post.Data)
|
||||
pageData, err = models_pages.RenderPostPage(app.Templates, app.Version, post.Data)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
models.PagesCache.Set(models_pages.PostPageTmplName, pageData)
|
||||
app.PagesCache.Set(models_pages.PostPageTmplName, pageData)
|
||||
}
|
||||
|
||||
sendPostPage(w, pageData.([]byte))
|
||||
|
|
|
@ -7,19 +7,19 @@ import (
|
|||
)
|
||||
|
||||
// Обработчик главной страницы
|
||||
func PostsPageHandler() http.HandlerFunc {
|
||||
func PostsPageHandler(app *models.App) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
|
||||
// Страничка рендерится только если ее нет в кэше
|
||||
pageData, ok := models.PagesCache.Get(models_pages.PostsPageTmplName)
|
||||
pageData, ok := app.PagesCache.Get(models_pages.PostsPageTmplName)
|
||||
if !ok {
|
||||
pageData, err = models_pages.RenderPostsPage(models.App.Templates, models.App.Version)
|
||||
pageData, err = app.Posts.RenderPostsPage(app.Templates, app.Version)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
models.PagesCache.Set(models_pages.PostsPageTmplName, pageData)
|
||||
app.PagesCache.Set(models_pages.PostsPageTmplName, pageData)
|
||||
}
|
||||
|
||||
sendPostsPage(w, pageData.([]byte))
|
||||
|
|
|
@ -2,55 +2,39 @@ package models
|
|||
|
||||
import (
|
||||
"html/template"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"main/mvc/models/models_pages"
|
||||
"time"
|
||||
)
|
||||
|
||||
// App хранит шаблоны и время запуска
|
||||
type app struct {
|
||||
type App struct {
|
||||
Cfg *Config // Сонфиг
|
||||
Posts models_pages.Posts // Посты
|
||||
Templates *template.Template // Шаблоны страниц
|
||||
PagesCache *Cache // Кэш (отрендеренные странички)
|
||||
Version int64 // Время запуска
|
||||
}
|
||||
|
||||
var (
|
||||
App = &app{}
|
||||
)
|
||||
|
||||
// Инициализирует приложение
|
||||
func InitApp() error {
|
||||
func InitApp() (*App, error) {
|
||||
var err error
|
||||
|
||||
App.Version = time.Now().Unix()
|
||||
app := &App{}
|
||||
|
||||
// Версия чтобы статика не кэшировалась
|
||||
app.Version = time.Now().Unix()
|
||||
// Загрузка конфига
|
||||
if app.Cfg, err = loadConfig(ConfigPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Загрузка постов
|
||||
if app.Posts, err = models_pages.LoadPosts(app.Cfg.PostsDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Загрузка шаблонов
|
||||
if err := App.loadTemplates(Cfg.TemplatesDir, Cfg.TemplatesExt); err != nil {
|
||||
return err
|
||||
if app.Templates, err = loadTemplates(app.Cfg.TemplatesDir, app.Cfg.TemplatesExt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Загрузка шаблонов
|
||||
func (a *app) loadTemplates(templatesPath string, ext string) error {
|
||||
tmpls := template.New("")
|
||||
|
||||
err := filepath.Walk(templatesPath, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !f.IsDir() && strings.HasSuffix(f.Name(), ext) {
|
||||
_, err = tmpls.ParseFiles(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Templates = tmpls
|
||||
return nil
|
||||
// Инициализация кэша
|
||||
app.PagesCache = initCache()
|
||||
return app, nil
|
||||
}
|
||||
|
|
|
@ -2,23 +2,23 @@ package models
|
|||
|
||||
import "sync"
|
||||
|
||||
type cache struct {
|
||||
type Cache struct {
|
||||
Data map[string]any
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
|
||||
var (
|
||||
PagesCache = cache{Data: make(map[string]any)}
|
||||
)
|
||||
func initCache() *Cache {
|
||||
return &Cache{Data: make(map[string]any)}
|
||||
}
|
||||
|
||||
func (c *cache) Get(key string) (any, bool) {
|
||||
func (c *Cache) Get(key string) (any, bool) {
|
||||
c.Mu.RLock()
|
||||
pageData, ok := c.Data[key]
|
||||
c.Mu.RUnlock()
|
||||
return pageData, ok
|
||||
}
|
||||
|
||||
func (c *cache) Set(key string, data any) {
|
||||
func (c *Cache) Set(key string, data any) {
|
||||
c.Mu.Lock()
|
||||
c.Data[key] = data
|
||||
c.Mu.Unlock()
|
||||
|
|
|
@ -5,7 +5,11 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
const (
|
||||
ConfigPath = "config.json"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
PostsDir string
|
||||
AssetsDir string
|
||||
TemplatesDir string
|
||||
|
@ -18,18 +22,15 @@ type config struct {
|
|||
Port string
|
||||
}
|
||||
|
||||
var (
|
||||
Cfg = &config{}
|
||||
)
|
||||
|
||||
func (c *config) Load(configPath string) error {
|
||||
func loadConfig(configPath string) (*Config, error) {
|
||||
cfg := &Config{}
|
||||
configFile, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(configFile, c)
|
||||
err = json.Unmarshal(configFile, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
|
@ -17,17 +17,12 @@ const (
|
|||
PostsPageTmplName = "posts.gohtml"
|
||||
)
|
||||
|
||||
type posts map[PostLink]*Post
|
||||
type Posts map[PostLink]*Post
|
||||
|
||||
var (
|
||||
allPosts = posts{}
|
||||
)
|
||||
func LoadPosts(dir string) (Posts, error) {
|
||||
|
||||
func GetPosts() posts {
|
||||
return allPosts
|
||||
}
|
||||
posts := Posts{}
|
||||
|
||||
func LoadPosts(dir string) error {
|
||||
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -46,25 +41,25 @@ func LoadPosts(dir string) error {
|
|||
|
||||
html := tools.MdToHTML(md)
|
||||
link := fmt.Sprintf("/%s/", strings.TrimSuffix(filepath.Base(path), ".md"))
|
||||
allPosts[PostLink(link)] = newPost(link, html)
|
||||
posts[PostLink(link)] = newPost(link, html)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
return posts, nil
|
||||
}
|
||||
|
||||
func RenderPostsPage(templates *template.Template, version int64) ([]byte, error) {
|
||||
func (p *Posts) RenderPostsPage(templates *template.Template, version int64) ([]byte, error) {
|
||||
var pageData bytes.Buffer
|
||||
|
||||
context := map[string]any{
|
||||
"version": version,
|
||||
"renderingTimestamp": time.Now().Unix(),
|
||||
"posts": allPosts,
|
||||
"posts": p,
|
||||
}
|
||||
|
||||
if err := templates.ExecuteTemplate(&pageData, PostsPageTmplName, context); err != nil {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func loadTemplates(templatesPath string, ext string) (*template.Template, error) {
|
||||
tmpls := template.New("")
|
||||
|
||||
err := filepath.Walk(templatesPath, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !f.IsDir() && strings.HasSuffix(f.Name(), ext) {
|
||||
_, err = tmpls.ParseFiles(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tmpls, nil
|
||||
}
|
Loading…
Reference in New Issue