download handler: support for verifying a digest in a HEAD request

for use in javascript uploads.
This commit is contained in:
Brad Fitzpatrick 2011-06-09 18:33:26 -07:00
parent 6f35e66385
commit 3c6c4207be
2 changed files with 29 additions and 6 deletions

View File

@ -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()
}

View File

@ -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
}
}