Test http-range resume download
This commit is contained in:
parent
b727d95327
commit
c9c457c270
@ -20,6 +20,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@ -44,6 +45,7 @@ var (
|
||||
"status-batch-403", "status-batch-404", "status-batch-410", "status-batch-422", "status-batch-500",
|
||||
"status-storage-403", "status-storage-404", "status-storage-410", "status-storage-422", "status-storage-500",
|
||||
"status-legacy-404", "status-legacy-410", "status-legacy-422", "status-legacy-403", "status-legacy-500",
|
||||
"status-batch-resume-206",
|
||||
}
|
||||
)
|
||||
|
||||
@ -284,9 +286,14 @@ func lfsBatchHandler(w http.ResponseWriter, r *http.Request, repo string) {
|
||||
}
|
||||
|
||||
type batchReq struct {
|
||||
Transfers []string `json:"transfers"`
|
||||
Operation string `json:"operation"`
|
||||
Objects []lfsObject `json:"objects"`
|
||||
}
|
||||
type batchResp struct {
|
||||
Transfer string `json:"transfer,omitempty"`
|
||||
Objects []lfsObject `json:"objects"`
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
tee := io.TeeReader(r.Body, buf)
|
||||
@ -304,6 +311,7 @@ func lfsBatchHandler(w http.ResponseWriter, r *http.Request, repo string) {
|
||||
|
||||
res := []lfsObject{}
|
||||
testingChunked := testingChunkedTransferEncoding(r)
|
||||
var transferChoice string
|
||||
for _, obj := range objs.Objects {
|
||||
action := objs.Operation
|
||||
|
||||
@ -337,6 +345,14 @@ func lfsBatchHandler(w http.ResponseWriter, r *http.Request, repo string) {
|
||||
o.Err = &lfsError{Code: 422, Message: "welp"}
|
||||
case "status-batch-500":
|
||||
o.Err = &lfsError{Code: 500, Message: "welp"}
|
||||
case "status-batch-resume-206":
|
||||
for _, t := range objs.Transfers {
|
||||
if t == "http-range" {
|
||||
transferChoice = "http-range"
|
||||
break
|
||||
}
|
||||
}
|
||||
fallthrough
|
||||
default: // regular 200 response
|
||||
if addAction {
|
||||
o.Actions = map[string]lfsLink{
|
||||
@ -355,7 +371,7 @@ func lfsBatchHandler(w http.ResponseWriter, r *http.Request, repo string) {
|
||||
res = append(res, o)
|
||||
}
|
||||
|
||||
ores := map[string][]lfsObject{"objects": res}
|
||||
ores := batchResp{Transfer: transferChoice, Objects: res}
|
||||
|
||||
by, err := json.Marshal(ores)
|
||||
if err != nil {
|
||||
@ -427,9 +443,32 @@ func storageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
case "GET":
|
||||
parts := strings.Split(r.URL.Path, "/")
|
||||
oid := parts[len(parts)-1]
|
||||
statusCode := 200
|
||||
byteLimit := 0
|
||||
resumeAt := int64(0)
|
||||
|
||||
if by, ok := largeObjects.Get(repo, oid); ok {
|
||||
w.Write(by)
|
||||
if len(by) == len("status-batch-resume-206") && string(by) == "status-batch-resume-206" {
|
||||
// Resume if header includes range, otherwise deliberately interrupt
|
||||
if rangeHdr := r.Header.Get("Range"); rangeHdr != "" {
|
||||
regex := regexp.MustCompile(`bytes=(\d+)\-.*`)
|
||||
match := regex.FindStringSubmatch(rangeHdr)
|
||||
if match != nil && len(match) > 1 {
|
||||
statusCode = 206
|
||||
resumeAt, _ = strconv.ParseInt(match[1], 10, 32)
|
||||
}
|
||||
} else {
|
||||
byteLimit = 10
|
||||
}
|
||||
}
|
||||
w.WriteHeader(statusCode)
|
||||
if byteLimit > 0 {
|
||||
w.Write(by[0:byteLimit])
|
||||
} else if resumeAt > 0 {
|
||||
w.Write(by[resumeAt:])
|
||||
} else {
|
||||
w.Write(by)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
45
test/test-resume-http-range.sh
Executable file
45
test/test-resume-http-range.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. "test/testlib.sh"
|
||||
|
||||
begin_test "resume-http-range"
|
||||
(
|
||||
set -e
|
||||
|
||||
reponame="$(basename "$0" ".sh")"
|
||||
setup_remote_repo "$reponame"
|
||||
|
||||
clone_repo "$reponame" $reponame
|
||||
|
||||
git lfs track "*.dat" 2>&1 | tee track.log
|
||||
grep "Tracking \*.dat" track.log
|
||||
|
||||
# this string announces to server that we want http-range support and to
|
||||
# interrupt the transfer when started from 0 to cause resume
|
||||
contents="status-batch-resume-206"
|
||||
contents_oid=$(calc_oid "$contents")
|
||||
|
||||
printf "$contents" > a.dat
|
||||
git add a.dat
|
||||
git add .gitattributes
|
||||
git commit -m "add a.dat" 2>&1 | tee commit.log
|
||||
git push origin master
|
||||
|
||||
assert_server_object "$reponame" "$contents_oid"
|
||||
|
||||
# delete local copy then fetch it back
|
||||
# server will abort the transfer mid way (so will error) when not resuming
|
||||
# then we can restart it
|
||||
rm -rf .git/lfs/objects
|
||||
git lfs fetch 2>&1 | tee fetchinterrupted.log
|
||||
refute_local_object "$contents_oid"
|
||||
|
||||
# now fetch again, this should try to resume and server should send remainder
|
||||
# this time (it does not cut short when Range is requested)
|
||||
GIT_TRACE=1 git lfs fetch 2>&1 | tee fetchresume.log
|
||||
grep "http-range: server accepted resume" fetchresume.log
|
||||
assert_local_object "$contents_oid" "${#contents}"
|
||||
|
||||
)
|
||||
end_test
|
||||
|
Loading…
Reference in New Issue
Block a user