mirror of https://github.com/perkeep/perkeep.git
server: use http.ServeContent and use cache headers in download handler
Change-Id: I5c24f39c86f6308b32167cf0d92ee68f801b9181
This commit is contained in:
parent
bcd57baf8f
commit
13105dad21
|
@ -67,3 +67,11 @@ func MimeTypeFromReader(r io.Reader) (mime string, reader io.Reader) {
|
|||
mime = MimeType(buf.Bytes())
|
||||
return mime, io.MultiReader(&buf, r)
|
||||
}
|
||||
|
||||
// MimeTypeFromReader takes a ReaderAt, sniffs the beginning of it,
|
||||
// and returns the MIME type if sniffed, else the empty string.
|
||||
func MIMETypeFromReaderAt(ra io.ReaderAt) (mime string) {
|
||||
var buf [1024]byte
|
||||
n, _ := ra.ReadAt(buf[:], 0)
|
||||
return MimeType(buf[:n])
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ package server
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"camlistore.org/pkg/blobref"
|
||||
"camlistore.org/pkg/blobserver"
|
||||
|
@ -28,6 +28,8 @@ import (
|
|||
"camlistore.org/pkg/schema"
|
||||
)
|
||||
|
||||
const oneYear = 365 * 86400 * time.Second
|
||||
|
||||
type DownloadHandler struct {
|
||||
Fetcher blobref.StreamingFetcher
|
||||
Cache blobserver.Storage
|
||||
|
@ -43,6 +45,11 @@ func (dh *DownloadHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request,
|
|||
http.Error(rw, "Invalid download method", 400)
|
||||
return
|
||||
}
|
||||
if req.Header.Get("If-Modified-Since") != "" {
|
||||
// Immutable, so any copy's a good copy.
|
||||
rw.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
fr, err := schema.NewFileReader(dh.storageSeekFetcher(), file)
|
||||
if err != nil {
|
||||
|
@ -52,16 +59,18 @@ func (dh *DownloadHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request,
|
|||
defer fr.Close()
|
||||
|
||||
schema := fr.FileSchema()
|
||||
rw.Header().Set("Content-Length", fmt.Sprintf("%d", schema.SumPartsSize()))
|
||||
h := rw.Header()
|
||||
h.Set("Content-Length", fmt.Sprintf("%d", schema.SumPartsSize()))
|
||||
h.Set("Expires", time.Now().Add(oneYear).Format(http.TimeFormat))
|
||||
|
||||
mimeType, reader := magic.MimeTypeFromReader(fr)
|
||||
mimeType := magic.MIMETypeFromReaderAt(fr)
|
||||
if dh.ForceMime != "" {
|
||||
mimeType = dh.ForceMime
|
||||
}
|
||||
if mimeType == "" {
|
||||
mimeType = "application/octet-stream"
|
||||
}
|
||||
rw.Header().Set("Content-Type", mimeType)
|
||||
h.Set("Content-Type", mimeType)
|
||||
if mimeType == "application/octet-stream" {
|
||||
// Chrome seems to silently do nothing on
|
||||
// application/octet-stream unless this is set.
|
||||
|
@ -70,7 +79,7 @@ func (dh *DownloadHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request,
|
|||
rw.Header().Set("Content-Disposition", "attachment; filename=file-"+file.String()+".dat")
|
||||
}
|
||||
|
||||
if req.Method == "HEAD" {
|
||||
if req.Method == "HEAD" && req.FormValue("verifycontents") != "" {
|
||||
vbr := blobref.Parse(req.FormValue("verifycontents"))
|
||||
if vbr == nil {
|
||||
return
|
||||
|
@ -79,22 +88,12 @@ func (dh *DownloadHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request,
|
|||
if hash == nil {
|
||||
return
|
||||
}
|
||||
io.Copy(hash, reader) // ignore errors, caught later
|
||||
io.Copy(hash, fr) // ignore errors, caught later
|
||||
if vbr.HashMatches(hash) {
|
||||
rw.Header().Set("X-Camli-Contents", vbr.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n, err := io.Copy(rw, reader)
|
||||
if err != nil {
|
||||
log.Printf("error serving download of file schema %s: %v", file, err)
|
||||
return
|
||||
}
|
||||
if size := schema.SumPartsSize(); n != int64(size) {
|
||||
log.Printf("error serving download of file schema %s: sent %d, expected size of %d",
|
||||
file, n, size)
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeContent(rw, req, "", time.Now(), fr)
|
||||
}
|
||||
|
|
|
@ -265,8 +265,7 @@ func (ih *ImageHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request, fil
|
|||
}
|
||||
|
||||
h := rw.Header()
|
||||
const oneYearish = 365 * 86400 * time.Second
|
||||
h.Set("Expires", time.Now().Add(oneYearish).Format(http.TimeFormat))
|
||||
h.Set("Expires", time.Now().Add(oneYear).Format(http.TimeFormat))
|
||||
h.Set("Last-Modified", time.Now().Format(http.TimeFormat))
|
||||
h.Set("Content-Type", imageContentTypeOfFormat(format))
|
||||
size := buf.Len()
|
||||
|
|
Loading…
Reference in New Issue