Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions s3util/uploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package s3util
import (
"bytes"
"encoding/xml"
"github.com/kr/s3"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"syscall"
"time"

"github.com/kr/s3"
)

// defined by amazon
Expand Down Expand Up @@ -190,11 +192,14 @@ func (u *uploader) putPart(p *part) error {
if resp.StatusCode != 200 {
return newRespError(resp)
}
s := resp.Header.Get("etag") // includes quote chars for some reason
if len(s) < 2 {
return fmt.Errorf("received invalid etag %q", s)

s := resp.Header.Get("etag")
s = strings.Trim(s, `"`) // includes quote chars for some reason
if s == "" {
return fmt.Errorf("received empty etag")
}
p.ETag = s[1 : len(s)-1]
p.ETag = s

return nil
}

Expand Down
69 changes: 38 additions & 31 deletions s3util/uploader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,37 +127,44 @@ func TestEmptyEtag(t *testing.T) {
t.Fatal("uploader panic", err)
}
}()
body := readClose{
strings.NewReader(`<UploadId>foo</UploadId>`),
make(closeCounter, 100),
}
c := *DefaultConfig
c.Client = &http.Client{
Transport: RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
resp := &http.Response{
StatusCode: 200,
Body: body,
Header: http.Header{
"Etag": {""},
},
}
return resp, nil
}),
}
u, err := newUploader("https://s3.amazonaws.com/foo/bar", nil, &c)
if err != nil {
t.Fatal("unexpected err", err)
}
const size = minPartSize + minPartSize/3
n, err := io.Copy(u, io.LimitReader(devZero, size))
if err == nil || err.Error() != `received invalid etag ""` {
t.Fatalf("expected err: %q", err)
}
if n != minPartSize {
t.Fatalf("wrote %d bytes want %d", n, minPartSize)

testEmptyEtag := func(emptyEtag string) {
body := readClose{
strings.NewReader(`<UploadId>foo</UploadId>`),
make(closeCounter, 100),
}
c := *DefaultConfig
c.Client = &http.Client{
Transport: RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
resp := &http.Response{
StatusCode: 200,
Body: body,
Header: http.Header{
"Etag": []string{emptyEtag},
},
}
return resp, nil
}),
}
u, err := newUploader("https://s3.amazonaws.com/foo/bar", nil, &c)
if err != nil {
t.Fatal("unexpected err", err)
}
const size = minPartSize + minPartSize/3
n, err := io.Copy(u, io.LimitReader(devZero, size))
if err == nil || err.Error() != `received empty etag` {
t.Fatalf("expected err: %q", err)
}
if n != minPartSize {
t.Fatalf("wrote %d bytes want %d", n, minPartSize)
}
err = u.Close()
if err == nil || err.Error() != `received empty etag` {
t.Fatalf("expected err: %q", err)
}
}
err = u.Close()
if err == nil || err.Error() != `received invalid etag ""` {
t.Fatalf("expected err: %q", err)

for _, emptyEtag := range []string{"", `""`} {
testEmptyEtag(emptyEtag)
}
}