Merge branch 'master' of danga.com:camlistore

This commit is contained in:
Brett Slatkin 2010-08-02 21:06:10 -07:00
commit 891a4d7434
5 changed files with 109 additions and 8 deletions

View File

@ -29,8 +29,36 @@ func handleGet(conn *http.Conn, req *http.Request) {
serverError(conn, err)
return
}
reqRange := getRequestedRange(req)
if reqRange.SkipBytes != 0 {
_, err = file.Seek(reqRange.SkipBytes, 0)
if err != nil {
serverError(conn, err)
return
}
}
var input io.Reader = file
if reqRange.LimitBytes != -1 {
input = io.LimitReader(file, reqRange.LimitBytes)
}
remainBytes := stat.Size - reqRange.SkipBytes
if reqRange.LimitBytes != -1 &&
reqRange.LimitBytes < remainBytes {
remainBytes = reqRange.LimitBytes
}
conn.SetHeader("Content-Type", "application/octet-stream")
bytesCopied, err := io.Copy(conn, file)
if !reqRange.IsWholeFile() {
conn.SetHeader("Content-Range",
fmt.Sprintf("bytes %d-%d/%d", reqRange.SkipBytes,
reqRange.SkipBytes + remainBytes,
stat.Size))
conn.WriteHeader(http.StatusPartialContent)
}
bytesCopied, err := io.Copy(conn, input)
// If there's an error at this point, it's too late to tell the client,
// as they've already been receiving bytes. But they should be smart enough
@ -44,9 +72,9 @@ func handleGet(conn *http.Conn, req *http.Request) {
}
return
}
if bytesCopied != stat.Size {
fmt.Fprintf(os.Stderr, "Error sending file: %v, copied= %d, not %d%v\n", blobRef,
bytesCopied, stat.Size)
if bytesCopied != remainBytes {
fmt.Fprintf(os.Stderr, "Error sending file: %v, copied=%d, not %d\n", blobRef,
bytesCopied, remainBytes)
closer, _, err := conn.Hijack()
if err != nil {
closer.Close()

49
blobserver/go/range.go Normal file
View File

@ -0,0 +1,49 @@
package main
import (
"http"
"regexp"
"strconv"
)
// Default is {0, -1} to read all of a file.
type requestedRange struct {
SkipBytes int64
LimitBytes int64 // or -1 to read all
}
func (rr *requestedRange) IsWholeFile() bool {
return rr.SkipBytes == 0 && rr.LimitBytes == -1;
}
var wholeRange = &requestedRange{0, -1}
var rangePattern = regexp.MustCompile(`bytes=([0-9]+)-([0-9]*)`)
func getRequestedRange(req *http.Request) *requestedRange {
rrange, ok := req.Header["Range"]
if !ok {
return wholeRange
}
return getRequestedRangeFromString(rrange)
}
func getRequestedRangeFromString(rrange string) *requestedRange {
matches := rangePattern.MatchStrings(rrange)
if len(matches) == 0 {
return wholeRange;
}
skipBytes, _ := strconv.Atoi64(matches[1])
lastByteInclusive := int64(-1)
if len(matches[2]) > 0 {
lastByteInclusive, _ = strconv.Atoi64(matches[2])
}
limitBytes := int64(-1)
if lastByteInclusive != -1 {
limitBytes = lastByteInclusive - skipBytes + 1
if limitBytes < 0 {
limitBytes = 0
}
}
return &requestedRange{skipBytes, limitBytes}
}

View File

@ -0,0 +1,7 @@
package main
import "testing"
func testRange(t *t.Testing) {
}

21
blobserver/go/upload-file.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
#
# Lame upload script for development testing only. Doesn't do the
# preupload step and hard-codes the Go server's upload path (not
# conformant to spec).
use strict;
my $file = shift or die
"Usage: upload-file.pl: <file>";
-r $file or die "$file isn't readable.";
-f $file or die "$file isn't a file.";
die "bogus filename" if $file =~ /[ <>&\!]/;
my $sha1 = `sha1sum $file`;
chomp $sha1;
$sha1 =~ s/\s.+//;
system("curl", "-u", "foo:foo", "-F", "sha1-$sha1=\@$file",
"http://127.0.0.1:3179/camli/upload") and die "upload failed.";
print "Uploaded http://127.0.0.1:3179/camli/sha1-$sha1\n";

View File

@ -1,4 +0,0 @@
#!/bin/sh
curl -u foo:foo -F sha1-7c63f74bbe0b1de55ec41ad0d9297a3762ecfdbc=@/bin/true http://127.0.0.1:3179/camli/upload