Skip to content
This repository was archived by the owner on Dec 20, 2024. It is now read-only.

Commit a347174

Browse files
committed
bugfix: cdn cannot re-download uncompleted task with header param
Signed-off-by: lowzj <[email protected]>
1 parent 359e474 commit a347174

File tree

4 files changed

+66
-20
lines changed

4 files changed

+66
-20
lines changed

supernode/daemon/mgr/cdn/downloader.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
errorType "github.com/dragonflyoss/Dragonfly/pkg/errortypes"
2727
"github.com/dragonflyoss/Dragonfly/pkg/httputils"
2828
"github.com/dragonflyoss/Dragonfly/pkg/rangeutils"
29+
"github.com/dragonflyoss/Dragonfly/supernode/httpclient"
2930
)
3031

3132
// download downloads the file from the original address and
@@ -43,20 +44,29 @@ func (cm *Manager) download(ctx context.Context, taskID, url string, headers map
4344
return nil, errors.Wrapf(errorType.ErrInvalidValue, "failed to calculate the breakRange: %v", err)
4445
}
4546

46-
if headers == nil {
47-
headers = make(map[string]string)
48-
}
4947
// check if Range in header? if Range already in Header, use this range directly
50-
if _, ok := headers["Range"]; !ok {
51-
headers["Range"] = httputils.ConstructRangeStr(breakRange)
48+
if !hasRange(headers) {
49+
headers = httpclient.CopyHeader(
50+
map[string]string{"Range": httputils.ConstructRangeStr(breakRange)},
51+
headers)
52+
5253
}
5354
checkCode = []int{http.StatusPartialContent}
5455
}
5556

56-
logrus.Infof("start to download for taskId(%s) with fileUrl: %s header: %v checkCode: %d", taskID, url, headers, checkCode)
57+
logrus.Infof("start to download for taskId(%s) with fileUrl: %s"+
58+
" header: %v checkCode: %d", taskID, url, headers, checkCode)
5759
return cm.originClient.Download(url, headers, checkStatusCode(checkCode))
5860
}
5961

62+
func hasRange(headers map[string]string) bool {
63+
if headers == nil {
64+
return false
65+
}
66+
_, ok := headers["Range"]
67+
return ok
68+
}
69+
6070
func checkStatusCode(statusCode []int) func(int) bool {
6171
return func(status int) bool {
6272
for _, s := range statusCode {

supernode/daemon/mgr/cdn/downloader_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ func (s *CDNDownloadTestSuite) TestDownload(c *check.C) {
105105
}
106106

107107
for _, v := range cases {
108+
headers := cloneMap(v.headers)
108109
resp, err := cm.download(context.TODO(), "", ts.URL, v.headers, v.startPieceNum, v.httpFileLength, v.pieceContSize)
110+
c.Check(headers, check.DeepEquals, v.headers)
109111
c.Check(v.errCheck(err), check.Equals, true)
110112

111113
c.Check(resp.StatusCode, check.Equals, v.exceptedStatusCode)
@@ -160,3 +162,17 @@ func Test_checkStatusCode(t *testing.T) {
160162
})
161163
}
162164
}
165+
166+
// ----------------------------------------------------------------------------
167+
// helper
168+
169+
func cloneMap(src map[string]string) map[string]string {
170+
if src == nil {
171+
return nil
172+
}
173+
target := make(map[string]string)
174+
for k, v := range src {
175+
target[k] = v
176+
}
177+
return target
178+
}

supernode/httpclient/origin_http_client.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,16 @@ func (client *OriginClient) GetContentLength(url string, headers map[string]stri
132132

133133
// IsSupportRange checks if the source url support partial requests.
134134
func (client *OriginClient) IsSupportRange(url string, headers map[string]string) (bool, error) {
135-
// set headers
136-
if headers == nil {
137-
headers = make(map[string]string)
138-
}
139-
headers["Range"] = "bytes=0-0"
135+
// set headers: headers is a reference to map, should not change it
136+
copied := CopyHeader(nil, headers)
137+
copied["Range"] = "bytes=0-0"
140138

141139
// send request
142-
resp, err := client.HTTPWithHeaders(http.MethodGet, url, headers, 4*time.Second)
140+
resp, err := client.HTTPWithHeaders(http.MethodGet, url, copied, 4*time.Second)
143141
if err != nil {
144142
return false, err
145143
}
146-
resp.Body.Close()
144+
_ = resp.Body.Close()
147145

148146
if resp.StatusCode == http.StatusPartialContent {
149147
return true, nil
@@ -157,20 +155,18 @@ func (client *OriginClient) IsExpired(url string, headers map[string]string, las
157155
return true, nil
158156
}
159157

160-
// set headers
161-
if headers == nil {
162-
headers = make(map[string]string)
163-
}
158+
// set headers: headers is a reference to map, should not change it
159+
copied := CopyHeader(nil, headers)
164160
if lastModified > 0 {
165161
lastModifiedStr, _ := netutils.ConvertTimeIntToString(lastModified)
166-
headers["If-Modified-Since"] = lastModifiedStr
162+
copied["If-Modified-Since"] = lastModifiedStr
167163
}
168164
if !stringutils.IsEmptyStr(eTag) {
169-
headers["If-None-Match"] = eTag
165+
copied["If-None-Match"] = eTag
170166
}
171167

172168
// send request
173-
resp, err := client.HTTPWithHeaders(http.MethodGet, url, headers, 4*time.Second)
169+
resp, err := client.HTTPWithHeaders(http.MethodGet, url, copied, 4*time.Second)
174170
if err != nil {
175171
return false, err
176172
}
@@ -222,3 +218,14 @@ func (client *OriginClient) HTTPWithHeaders(method, url string, headers map[stri
222218
}
223219
return httpClient.Do(req)
224220
}
221+
222+
// CopyHeader copies the src to dst and return a non-nil dst map.
223+
func CopyHeader(dst, src map[string]string) map[string]string {
224+
if dst == nil {
225+
dst = make(map[string]string)
226+
}
227+
for k, v := range src {
228+
dst[k] = v
229+
}
230+
return dst
231+
}

supernode/httpclient/origin_http_client_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,16 @@ func (s *OriginHTTPClientTestSuite) TestRegisterTLSConfig(c *check.C) {
9898
c.Assert(resp, check.NotNil)
9999
c.Assert(resp.ContentLength, check.Equals, int64(-1))
100100
}
101+
102+
func (s *OriginHTTPClientTestSuite) TestCopyHeader(c *check.C) {
103+
dst := CopyHeader(nil, nil)
104+
c.Check(dst, check.NotNil)
105+
c.Check(len(dst), check.Equals, 0)
106+
107+
src := map[string]string{"test": "1"}
108+
dst = CopyHeader(nil, src)
109+
c.Check(dst, check.DeepEquals, src)
110+
111+
dst["test"] = "2"
112+
c.Check(src["test"], check.Equals, "1")
113+
}

0 commit comments

Comments
 (0)