pages-server/pagerouter/pagerouter.go
hazycora edd35305e6
All checks were successful
Deploy to VPS / build_site (push) Successful in 5s
make requests add .html & .htm file extensions as fallback
this was in the JS version, and forgotten in the port
2024-04-26 14:59:19 -05:00

134 lines
3.2 KiB
Go

package pagerouter
import (
"encoding/json"
"fmt"
"path"
"regexp"
"strings"
"time"
"git.gay/gitgay/pages/cache"
"git.gay/gitgay/pages/errors"
"git.gay/gitgay/pages/forgejo"
"git.gay/gitgay/pages/redirects"
"github.com/rs/zerolog/log"
)
var (
commentsRe = regexp.MustCompile(`#.*?$`)
PAGE_CACHE_TTL = time.Hour * 24
pageCache = cache.NewMemCache[*PageRouter]("page", PAGE_CACHE_TTL)
)
func GetPage(info *Target) (pageRouter *PageRouter, err error) {
pageCacheKey := fmt.Sprintf("%s:%s:%s", info.Repository.Owner, info.Repository.Name, info.SHA)
pageRouter, err = pageCache.Get(pageCacheKey)
if err == nil {
return
}
files, err := forgejo.GetTree(info.Repository.Owner, info.Repository.Name, info.SHA)
if err != nil {
err = errors.NewErrorCouldNotGetTree()
return
}
pageRouter = &PageRouter{
Info: info,
Files: files,
}
if domains, ok := files[".domains"]; ok && domains.Type == "blob" {
var bytes []byte
bytes, err = domains.Bytes()
if err != nil {
return
}
pageRouter.Domains = strings.Split(string(commentsRe.ReplaceAll(bytes, []byte(""))), "\n")
}
if settings, ok := files[".pages.json"]; ok && settings.Type == "blob" {
var bytes []byte
bytes, err = settings.Bytes()
if err != nil {
return
}
err = json.Unmarshal(bytes, &pageRouter.Settings)
if err != nil {
// Logging this error, but otherwise ignoring it as it's not critical
log.Err(err).Str("owner", pageRouter.Info.Repository.Owner).Str("repo", pageRouter.Info.Repository.Name).Msg("Could not unmarshal .pages.json")
} else {
pageRouter.Settings.BasePath = strings.Trim(path.Clean(pageRouter.Settings.BasePath), "/")
if pageRouter.Settings.BasePath == "." {
pageRouter.Settings.BasePath = ""
}
if pageRouter.Settings.BasePath != "" && !strings.HasSuffix(pageRouter.Settings.BasePath, "/") {
pageRouter.Settings.BasePath += "/"
}
}
}
if redirectFile, ok := files["_redirects"]; ok && redirectFile.Type == "blob" {
var bytes []byte
bytes, err = redirectFile.Bytes()
if err != nil {
return
}
var engine *redirects.RedirectEngine
engine, err = redirects.ParseRedirects(string(bytes))
if err != nil {
return
}
pageRouter.Redirects = engine
}
CleanPathsOfRouter(pageRouter)
err = pageCache.Set(pageCacheKey, pageRouter)
if err != nil {
log.Err(err).Msg("Could not cache page")
return
}
return
}
func tryPaths(pr *PageRouter, paths []string) (file *forgejo.TreeFile, ok bool) {
for _, path := range paths {
var found forgejo.TreeFile
found, ok = pr.Files[path]
if ok && found.Type == "blob" {
file = &found
return
}
}
return nil, false
}
func (pr *PageRouter) GetFile(filePath string) (file *forgejo.TreeFile, isIndex bool, err error) {
if pr.Info.Repository.Private && !pr.Settings.AllowPrivate {
err = errors.NewErrorNotFound()
return
}
filePath = trimSlashes(filePath)
var dir string
if filePath != "" {
found, ok := tryPaths(pr, []string{filePath, filePath + ".html", filePath + ".htm", filePath + ".md"})
if ok {
file = found
return
}
dir = filePath + "/"
}
isIndex = true
index, ok := tryPaths(pr, []string{dir + "index.html", dir + "index.htm", dir + "README.md"})
if ok {
file = index
return
}
err = errors.NewErrorNotFound()
return
}