-
Notifications
You must be signed in to change notification settings - Fork 5
/
checksum.go
55 lines (47 loc) · 1.08 KB
/
checksum.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package tos
import (
"crypto/md5"
"encoding/hex"
"errors"
"hash"
"io"
"strings"
)
var (
ErrETagMissMatch = errors.New("tos: ETag miss match")
)
// ETagCheckReadCloser checks ETag on read EOF
type ETagCheckReadCloser struct {
reader io.Reader
closer io.Closer
checksum hash.Hash
eTag string
requestID string
}
func NewETagCheckReadCloser(reader io.ReadCloser, eTag, requestID string) *ETagCheckReadCloser {
checksum := md5.New()
return &ETagCheckReadCloser{
reader: io.TeeReader(reader, checksum),
closer: reader,
checksum: checksum,
eTag: strings.Trim(eTag, `"`),
requestID: requestID,
}
}
func (ec *ETagCheckReadCloser) Read(p []byte) (n int, err error) {
n, err = ec.reader.Read(p)
if err == io.EOF && len(ec.eTag) > 0 {
sum := ec.checksum.Sum(nil)
if hexSum := hex.EncodeToString(sum); hexSum != ec.eTag {
return n, &ChecksumError{
RequestID: ec.requestID,
ExpectedChecksum: ec.eTag,
ActualChecksum: hexSum,
}
}
}
return n, err
}
func (ec *ETagCheckReadCloser) Close() error {
return ec.closer.Close()
}