package pages import ( "mime" "net/http" "strings" "time" "git.polynom.me/rio/internal/constants" "git.polynom.me/rio/internal/repo" "github.com/patrickmn/go-cache" log "github.com/sirupsen/logrus" ) var ( pageCache = cache.New(6*time.Hour, 1*time.Hour) ) type PageContentCache struct { Content []byte mimeType string RequestedAt time.Time } func makePageContentCacheEntry(username, path string) string { return username + ":" + path } func ServeFile(username, reponame, path string, giteaClient *repo.GiteaClient, w http.ResponseWriter) { // Provide a default if path == "" { path = "/index.html" } // Strip away a starting / as it messes with Gitea if path[:1] == "/" { path = path[1:] } key := makePageContentCacheEntry(username, path) entry, found := pageCache.Get(key) var content []byte var mimeType string var err error var since *time.Time = nil if found { log.Debugf("Returning %s from cache", path) content = entry.(PageContentCache).Content mimeType = entry.(PageContentCache).mimeType sinceRaw := entry.(PageContentCache).RequestedAt since = &sinceRaw } content, changed, err := giteaClient.GetFile( username, reponame, constants.PagesBranch, path, since, ) if err != nil { if !found { log.Errorf("Failed to get file %s/%s/%s (%s)", username, reponame, path, err) w.WriteHeader(404) } else { log.Debugf("Request failed but page %s is cached in memory", path) w.WriteHeader(200) w.Header().Set("Content-Type", mimeType) w.Write(content) } return } if found && !changed { log.Debugf("Page %s is unchanged and cached in memory", path) w.WriteHeader(200) w.Header().Set("Content-Type", mimeType) w.Write(content) return } pathParts := strings.Split(path, ".") ext := pathParts[len(pathParts)-1] mimeType = mime.TypeByExtension("." + ext) now := time.Now() pageCache.Set( key, PageContentCache{ content, mimeType, now, }, cache.DefaultExpiration, ) log.Debugf("Page %s requested from Gitea and cached in memory at %v", path, now) w.Header().Set("Content-Type", mimeType) w.WriteHeader(200) w.Write(content) }