package controllers import ( "bytes" "fmt" "main/mvc/models" "main/tools" "net/http" "github.com/gin-gonic/gin" ) // Задает маршруты для страниц вида tmplname/id.html, где необходим список всех постов func PageByName(tmplname string, group *gin.RouterGroup, s *models.Site) { group.GET(fmt.Sprintf("/%s/:id", tmplname), PageValidationMiddleware(s), func(c *gin.Context) { pageNumber, _ := c.Get("pageNumber") pageContext := models.NewPage(s, s.Posts, pageNumber.(int), AccessLvl(c), "") page, err := getPageByName(c, s, tmplname, pageNumber.(int), pageContext) if err != nil { c.String(http.StatusInternalServerError, "Ошибка рендеринга: %v", err) return } sendPage(c, page) }) } // Вынесенный общий код для получения страницы func getPageByName(c *gin.Context, s *models.Site, tmplname string, pageNumber int, pageContext *models.Page) (string, error) { var page string var err error if AccessLvl(c) != 0 { // Для админа - рендер без кэширования page, err = RenderPage(pageContext, tmplname, s) } else { key := fmt.Sprintf("%s%d", tmplname, pageNumber) // Попытка получить страницу из кэша if cachedPage, err := s.Cache.Get(key); err == nil { page = cachedPage.(string) } else { // Нет в кэше => рендерим page, err = RenderPage(pageContext, tmplname, s) if err == nil { // Сжимаю по возможности и добавляю в кэш go func() { compressedPage, err := tools.MinifyStringHtml(page) if err != nil { s.Cache.Set(key, page, -1) } else { s.Cache.Set(key, compressedPage, -1) } }() } } } return page, err } func SearchPage(tmplname string, group *gin.RouterGroup, s *models.Site) { group.GET(fmt.Sprintf("/%s/:id", tmplname), PageValidationMiddleware(s), func(c *gin.Context) { searchSubstring := c.Query("search") pageNumber, _ := c.Get("pageNumber") // Валидная страничка, рендерим page, err := getSearchPage(c, s, tmplname, pageNumber.(int), searchSubstring) if err != nil { c.String(http.StatusInternalServerError, "Ошибка рендеринга: %v", err) return } sendPage(c, page) }) } // Вынесенный общий код func getSearchPage(c *gin.Context, s *models.Site, tmplname string, pageNumber int, searchSubstring string) (string, error) { var page string var err error if AccessLvl(c) != 0 { // кэширую только странички по тегам // Для админа - рендер без кэширования posts := s.Posts.GetPostListBySubstring(searchSubstring) // посты, содержащие искомую подстроку pageContext := models.NewPage(s, posts, pageNumber, AccessLvl(c), searchSubstring) page, err = RenderPage(pageContext, tmplname, s) } else { key := fmt.Sprintf("%s%d%s", tmplname, pageNumber, searchSubstring) if cachedPage, err := s.Cache.Get(key); err == nil { page = cachedPage.(string) } else { // Нет в кэше => рендерим posts := s.Posts.GetPostListBySubstring(searchSubstring) pageContext := models.NewPage(s, posts, pageNumber, AccessLvl(c), searchSubstring) page, err = RenderPage(pageContext, tmplname, s) // если нет ошибки и список постов не пустой, то надо добавить в кэш if err == nil && len(posts) > 0 { // Сжимаю по возможности и добавляю в кэш go func() { compressedPage, err := tools.MinifyStringHtml(page) if err != nil { s.Cache.Set(key, page, -1) } else { s.Cache.Set(key, compressedPage, -1) } }() } } } return page, err } func RenderPage(pageContext *models.Page, tmplname string, s *models.Site) (string, error) { var buffer bytes.Buffer if err := s.Tmpl.ExecuteTemplate( &buffer, fmt.Sprintf("%s.gohtml", tmplname), pageContext); err != nil { return "", err } return buffer.String(), nil } func sendPage(c *gin.Context, page string) { c.Header("Content-Type", "text/html; charset=utf-8") c.String(http.StatusOK, page) }