max-age is now fully respected.
This commit is contained in:
parent
d8aa42f7ec
commit
af6ada6bd0
11
cache/cache.go
vendored
11
cache/cache.go
vendored
@ -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
|
// 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.
|
// 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
|
// 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
|
// not, a downloader and live reader are created.
|
||||||
// used to force a new download to be created.
|
func (c *Cache) GetReader(rawurl string, maxAge time.Duration) (Reader, error) {
|
||||||
func (c *Cache) GetReader(rawurl string, force bool) (Reader, error) {
|
|
||||||
hash, jsonFilename, dataFilename := c.getFilenames(rawurl)
|
hash, jsonFilename, dataFilename := c.getFilenames(rawurl)
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
@ -66,12 +65,14 @@ func (c *Cache) GetReader(rawurl string, force bool) (Reader, error) {
|
|||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else if !force {
|
} else {
|
||||||
r, err := newDiskReader(jsonFilename, dataFilename)
|
r, err := newDiskReader(jsonFilename, dataFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
log.Println("[HIT]", rawurl)
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
7
cache/downloader.go
vendored
7
cache/downloader.go
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DownloadError conveys information about a download request that failed.
|
// 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"),
|
ContentType: resp.Header.Get("Content-Type"),
|
||||||
LastModified: resp.Header.Get("Last-Modified"),
|
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 {
|
if err = d.entry.Save(jsonFilename); err != nil {
|
||||||
d.err = err
|
d.err = err
|
||||||
return
|
return
|
||||||
|
19
server.go
19
server.go
@ -11,6 +11,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server acts as an HTTP proxy, returning entries from the cache whenever
|
// Server acts as an HTTP proxy, returning entries from the cache whenever
|
||||||
@ -33,29 +34,21 @@ func rewrite(rawurl string) string {
|
|||||||
return rawurl
|
return rawurl
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldForce(req *http.Request) bool {
|
func maxAge(req *http.Request) time.Duration {
|
||||||
d, err := cacheobject.ParseRequestCacheControl(req.Header.Get("Cache-Control"))
|
d, err := cacheobject.ParseRequestCacheControl(req.Header.Get("Cache-Control"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if d.MaxAge == 0 || d.NoCache {
|
return time.Duration(d.MaxAge)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
return 0
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) writeHeaders(w http.ResponseWriter, e *cache.Entry) {
|
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)
|
l, err := strconv.ParseInt(e.ContentLength, 10, 64)
|
||||||
if err == nil && l >= 0 {
|
if err == nil && l >= 0 {
|
||||||
w.Header().Set("Content-Length", e.ContentLength)
|
w.Header().Set("Content-Length", e.ContentLength)
|
||||||
}
|
}
|
||||||
if e.LastModified != "" {
|
w.Header().Set("Content-Type", e.ContentType)
|
||||||
w.Header().Set("Last-Modified", e.LastModified)
|
w.Header().Set("Last-Modified", e.LastModified)
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusOK)
|
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)
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, err := s.cache.GetReader(rewrite(req.RequestURI), shouldForce(req))
|
r, err := s.cache.GetReader(rewrite(req.RequestURI), maxAge(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
log.Println("[ERR]", err)
|
log.Println("[ERR]", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user