mirror of https://github.com/perkeep/perkeep.git
download handler: support for verifying a digest in a HEAD request
for use in javascript uploads.
This commit is contained in:
parent
6f35e66385
commit
3c6c4207be
|
@ -85,7 +85,7 @@ func (o *BlobRef) Equals(other *BlobRef) bool {
|
|||
func (o *BlobRef) Hash() hash.Hash {
|
||||
fn, ok := supportedDigests[o.hashName]
|
||||
if !ok {
|
||||
return nil
|
||||
return nil // TODO: return an error here, not nil
|
||||
}
|
||||
return fn()
|
||||
}
|
||||
|
|
|
@ -211,6 +211,10 @@ func (ui *UIHandler) storageSeekFetcher() (blobref.SeekFetcher, os.Error) {
|
|||
}
|
||||
|
||||
func (ui *UIHandler) serveDownload(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != "GET" && req.Method != "HEAD" {
|
||||
http.Error(rw, "Invalid download method", 400)
|
||||
return
|
||||
}
|
||||
if ui.Storage == nil {
|
||||
http.Error(rw, "No BlobRoot configured", 500)
|
||||
return
|
||||
|
@ -230,8 +234,8 @@ func (ui *UIHandler) serveDownload(rw http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
blobref := blobref.Parse(m[1])
|
||||
if blobref == nil {
|
||||
fbr := blobref.Parse(m[1])
|
||||
if fbr == nil {
|
||||
http.Error(rw, "Invalid blobref", 400)
|
||||
return
|
||||
}
|
||||
|
@ -241,24 +245,43 @@ func (ui *UIHandler) serveDownload(rw http.ResponseWriter, req *http.Request) {
|
|||
filename = filename[1:] // remove leading slash
|
||||
}
|
||||
|
||||
fr, err := schema.NewFileReader(fetchSeeker, blobref)
|
||||
fr, err := schema.NewFileReader(fetchSeeker, fbr)
|
||||
if err != nil {
|
||||
http.Error(rw, "Can't serve file: "+err.String(), 500)
|
||||
return
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
// TODO: fr.FileSchema() and guess a mime type? For now:
|
||||
schema := fr.FileSchema()
|
||||
rw.Header().Set("Content-Type", "application/octet-stream")
|
||||
rw.Header().Set("Content-Length", fmt.Sprintf("%d", schema.Size))
|
||||
|
||||
if req.Method == "HEAD" {
|
||||
vbr := blobref.Parse(req.FormValue("verifycontents"))
|
||||
if vbr == nil {
|
||||
return
|
||||
}
|
||||
hash := vbr.Hash()
|
||||
if hash == nil {
|
||||
return
|
||||
}
|
||||
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, fr)
|
||||
log.Printf("For %q request of %s: copied %d, %v", req.Method, req.URL.RawPath, n, err)
|
||||
if err != nil {
|
||||
log.Printf("error serving download of file schema %s: %v", blobref, err)
|
||||
log.Printf("error serving download of file schema %s: %v", fbr, err)
|
||||
return
|
||||
}
|
||||
if n != int64(schema.Size) {
|
||||
log.Printf("error serving download of file schema %s: sent %d, expected size of %d",
|
||||
blobref, n, schema.Size)
|
||||
fbr, n, schema.Size)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue