/
chunked_body_wrapper.go
92 lines (84 loc) · 2.21 KB
/
chunked_body_wrapper.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package object
import (
"cloudsidecar/pkg/logging"
"errors"
"io"
"strconv"
"strings"
)
type ReaderWrapper struct {
Reader io.ReadCloser
}
func (wrapper ReaderWrapper) Seek(offset int64, whence int) (int64, error) {
return 0, errors.New("invalid operation")
}
func (wrapper ReaderWrapper) Read(p []byte) (n int, err error) {
return (wrapper.Reader).Read(p)
}
type ChunkedReaderWrapper struct {
Reader *io.ReadCloser
ChunkNextPosition int
ChunkSize int
}
func (wrapper *ChunkedReaderWrapper) ReadHeaderGetChunkSize() (i int, err error) {
chunkedHeader, err := wrapper.ReadHeader()
if err != nil {
logging.Log.Error("Error reading header %s", err)
return 0, err
}
logging.Log.Debug("Read header %s\n", chunkedHeader)
chunkedSplit := strings.SplitN(chunkedHeader, ";", 2)
chunkSize, err := strconv.ParseInt(chunkedSplit[0], 16, 32)
return int(chunkSize), err
}
func (wrapper *ChunkedReaderWrapper) ReadHeader() (s string, err error) {
oneByte := make([]byte, 1)
readCount := 0
header := make([]byte, 4096)
for {
_, err := io.ReadFull(*wrapper.Reader, oneByte)
if err != nil {
return string(header[:readCount]), err
}
if oneByte[0] == '\r' {
// read \n
io.ReadFull(*wrapper.Reader, oneByte)
if readCount != 0 {
return string(header[:readCount]), nil
} else {
// \r is first char
io.ReadFull(*wrapper.Reader, oneByte)
}
}
if readCount >= len(header) {
return string(header[:readCount]), io.ErrShortBuffer
}
header[readCount] = oneByte[0]
readCount++
}
}
func (wrapper *ChunkedReaderWrapper) Read(p []byte) (n int, err error) {
if wrapper.ChunkNextPosition == -1 {
wrapper.ChunkNextPosition = 0
chunkSize, err := wrapper.ReadHeaderGetChunkSize()
logging.Log.Debug("Chunk size %d\n", chunkSize)
if err != nil {
logging.Log.Error("Error reading header %s", err)
return 0, err
}
wrapper.ChunkSize = chunkSize
if chunkSize == 0 {
return 0, io.EOF
}
}
bytesLeft := wrapper.ChunkSize - wrapper.ChunkNextPosition
pLen := len(p)
if bytesLeft <= pLen {
n, err = io.ReadFull(*wrapper.Reader, p[:bytesLeft])
wrapper.ChunkNextPosition = -1
} else {
n, err = io.ReadFull(*wrapper.Reader, p)
wrapper.ChunkNextPosition += n
}
return n, err
}