diff --git a/cache/cache.go b/cache/cache.go index 863ff31..1b78b99 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -53,9 +53,8 @@ func (c *Cache) getFilenames(rawurl string) (hash, jsonFilename, dataFilename st // GetReader obtains a Reader for the specified rawurl. If a downloader // currently exists for the URL, a live reader is created and connected to it. // If the URL exists in the cache, it is read using the standard file API. If -// not, a downloader and live reader are created. The force parameter can be -// used to force a new download to be created. -func (c *Cache) GetReader(rawurl string, force bool) (Reader, error) { +// not, a downloader and live reader are created. +func (c *Cache) GetReader(rawurl string, maxAge time.Duration) (Reader, error) { hash, jsonFilename, dataFilename := c.getFilenames(rawurl) c.mutex.Lock() defer c.mutex.Unlock() @@ -66,12 +65,14 @@ func (c *Cache) GetReader(rawurl string, force bool) (Reader, error) { if !os.IsNotExist(err) { return nil, err } - } else if !force { + } else { r, err := newDiskReader(jsonFilename, dataFilename) if err != nil { return nil, err } - if e, _ := r.GetEntry(); e.Complete { + e, _ := r.GetEntry() + lastModified, _ := time.Parse(http.TimeFormat, e.LastModified) + if lastModified.Before(time.Now().Add(maxAge)) || e.Complete { log.Println("[HIT]", rawurl) return r, nil } diff --git a/cache/downloader.go b/cache/downloader.go index f3c2191..a5a1824 100644 --- a/cache/downloader.go +++ b/cache/downloader.go @@ -6,6 +6,7 @@ import ( "os" "strconv" "sync" + "time" ) // DownloadError conveys information about a download request that failed. @@ -66,6 +67,12 @@ func newDownloader(rawurl, jsonFilename, dataFilename string) *downloader { ContentType: resp.Header.Get("Content-Type"), LastModified: resp.Header.Get("Last-Modified"), } + if d.entry.ContentType == "" { + d.entry.ContentType = "application/octet-stream" + } + if d.entry.LastModified == "" { + d.entry.LastModified = time.Now().Format(http.TimeFormat) + } if err = d.entry.Save(jsonFilename); err != nil { d.err = err return diff --git a/server.go b/server.go index 26bc363..e817317 100644 --- a/server.go +++ b/server.go @@ -11,6 +11,7 @@ import ( "net/url" "strconv" "strings" + "time" ) // Server acts as an HTTP proxy, returning entries from the cache whenever @@ -33,29 +34,21 @@ func rewrite(rawurl string) string { return rawurl } -func shouldForce(req *http.Request) bool { +func maxAge(req *http.Request) time.Duration { d, err := cacheobject.ParseRequestCacheControl(req.Header.Get("Cache-Control")) if err != nil { - if d.MaxAge == 0 || d.NoCache { - return true - } + return time.Duration(d.MaxAge) } - return false + return 0 } func (s *Server) writeHeaders(w http.ResponseWriter, e *cache.Entry) { - if e.ContentType != "" { - w.Header().Set("Content-Type", e.ContentType) - } else { - w.Header().Set("Content-Type", "application/octet-stream") - } l, err := strconv.ParseInt(e.ContentLength, 10, 64) if err == nil && l >= 0 { w.Header().Set("Content-Length", e.ContentLength) } - if e.LastModified != "" { - w.Header().Set("Last-Modified", e.LastModified) - } + w.Header().Set("Content-Type", e.ContentType) + w.Header().Set("Last-Modified", e.LastModified) w.WriteHeader(http.StatusOK) } @@ -67,7 +60,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } - r, err := s.cache.GetReader(rewrite(req.RequestURI), shouldForce(req)) + r, err := s.cache.GetReader(rewrite(req.RequestURI), maxAge(req)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Println("[ERR]", err)