test downloads with legacy git media header

This fixes a subtle bug where the size returned by Download() is the
size of the object AND the header, when it should be the size of just
the object.
This commit is contained in:
Rick Olson 2015-02-13 16:30:47 -07:00
parent 00a381dcc9
commit 2f6767a44b
2 changed files with 54 additions and 9 deletions

@ -66,12 +66,13 @@ func Download(oidPath string) (io.ReadCloser, int64, *WrappedError) {
return nil, 0, wErr
}
if ok, wErr := validateMediaHeader(contentType, res.Body); !ok {
ok, headerSize, wErr := validateMediaHeader(contentType, res.Body)
if !ok {
setErrorResponseContext(wErr, res)
return nil, 0, wErr
}
return res.Body, res.ContentLength, nil
return res.Body, res.ContentLength - int64(headerSize), nil
}
func Upload(oidPath, filename string, cb CopyCallback) *WrappedError {
@ -302,32 +303,35 @@ func callPost(filehash, filename string) (*linkMeta, int, error) {
return nil, res.StatusCode, nil
}
func validateMediaHeader(contentType string, reader io.Reader) (bool, *WrappedError) {
func validateMediaHeader(contentType string, reader io.Reader) (bool, int, *WrappedError) {
mediaType, params, err := mime.ParseMediaType(contentType)
var headerSize int
if err != nil {
return false, Errorf(err, "Invalid Media Type: %s", contentType)
return false, headerSize, Errorf(err, "Invalid Media Type: %s", contentType)
}
if mediaType == gitMediaType {
givenHeader, ok := params["header"]
if !ok {
return false, Error(fmt.Errorf("Missing Git Media header in %s", contentType))
return false, headerSize, Error(fmt.Errorf("Missing Git Media header in %s", contentType))
}
fullGivenHeader := "--" + givenHeader + "\n"
headerSize = len(fullGivenHeader)
header := make([]byte, len(fullGivenHeader))
header := make([]byte, headerSize)
_, err = io.ReadAtLeast(reader, header, len(fullGivenHeader))
if err != nil {
return false, Errorf(err, "Error reading response body.")
return false, headerSize, Errorf(err, "Error reading response body.")
}
if string(header) != fullGivenHeader {
return false, Error(fmt.Errorf("Invalid header: %s expected, got %s", fullGivenHeader, header))
return false, headerSize, Error(fmt.Errorf("Invalid header: %s expected, got %s", fullGivenHeader, header))
}
}
return true, nil
return true, headerSize, nil
}
func doRequest(req *http.Request, creds Creds) (*http.Response, *WrappedError) {

@ -9,6 +9,47 @@ import (
"testing"
)
func TestDownloadWithMediaHeader(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
tmp := tempdir(t)
defer server.Close()
defer os.RemoveAll(tmp)
mux.HandleFunc("/media/objects/oid", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.WriteHeader(405)
return
}
head := w.Header()
head.Set("Content-Type", "application/vnd.git-media; header=download-header")
head.Set("Content-Length", "22")
w.WriteHeader(200)
w.Write([]byte("--download-header\ntest"))
})
Config.SetConfig("hawser.url", server.URL+"/media")
reader, size, wErr := Download("whatever/oid")
if wErr != nil {
t.Fatalf("unexpected error: %s", wErr)
}
defer reader.Close()
if size != 4 {
t.Errorf("unexpected size: %d", size)
}
by, err := ioutil.ReadAll(reader)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if body := string(by); body != "test" {
t.Errorf("unexpected body: %s", body)
}
}
func TestPut(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)