diff --git a/test/cli/fixtures/README.md b/test/cli/fixtures/README.md index bf1886ab3f1..dab926be480 100644 --- a/test/cli/fixtures/README.md +++ b/test/cli/fixtures/README.md @@ -37,3 +37,36 @@ echo $FIXTURE_CID # bafybeig3yoibxe56aolixqa4zk55gp5sug3qgaztkakpndzk2b2ynobd4i ipfs dag export $FIXTURE_CID > TestGatewayHAMTDirectory.car ``` + +TestGatewayMultiRange.car generated with: + + +```sh +ipfs version +# ipfs version 0.19.0 + +export FILE_CID=bafybeiae5abzv6j3ucqbzlpnx3pcqbr2otbnpot7d2k5pckmpymin4guau +export IPFS_PATH=$(mktemp -d) + +# Init and start daemon, ensure we have an empty repository. +ipfs init --empty-repo +ipfs daemon &> /dev/null & +export IPFS_PID=$! + +# Get a specific byte range from the file. +curl http://127.0.0.1:8080/ipfs/$FILE_CID -i -H "Range: bytes=1276-1279, 29839070-29839080" +kill $IPFS_PID + +# Get the list with all the downloaded refs and sanity check. +ipfs refs local > required_refs +cat required_refs | wc -l +# 19 + +# Make and export our fixture. +ipfs files mkdir --cid-version 1 /fixtures +cat required_refs | xargs -I {} ipfs files cp /ipfs/{} /fixtures/{} +export FIXTURE_CID=$(ipfs files stat --hash /fixtures/) +echo $FIXTURE_CID +# bafybeicgsg3lwyn3yl75lw7sn4zhyj5dxtb7wfxwscpq6yzippetmr2w3y +ipfs dag export $FIXTURE_CID > TestGatewayMultiRange.car +``` diff --git a/test/cli/gateway_range_test.go b/test/cli/gateway_range_test.go index 2091c3c6c86..2d8ce1a3eff 100644 --- a/test/cli/gateway_range_test.go +++ b/test/cli/gateway_range_test.go @@ -40,3 +40,61 @@ func TestGatewayHAMTDirectory(t *testing.T) { resp := client.Get(fmt.Sprintf("/ipfs/%s/", hamtCid)) assert.Equal(t, http.StatusOK, resp.StatusCode) } + +func TestGatewayHAMTRanges(t *testing.T) { + t.Parallel() + + const ( + // fileCid is the CID of the large HAMT-sharded file. + fileCid = "bafybeiae5abzv6j3ucqbzlpnx3pcqbr2otbnpot7d2k5pckmpymin4guau" + + // fixtureCid is the CID of root of the DAG that is a subset of fileCid DAG + // representing the minimal set of blocks necessary for a simple byte range request. + fixtureCid = "bafybeicgsg3lwyn3yl75lw7sn4zhyj5dxtb7wfxwscpq6yzippetmr2w3y" + ) + + // Start node + h := harness.NewT(t) + node := h.NewNode().Init("--empty-repo", "--profile=test").StartDaemon("--offline") + client := node.GatewayClient() + + // Import fixtures + r, err := os.Open("./fixtures/TestGatewayMultiRange.car") + assert.NoError(t, err) + defer r.Close() + err = node.IPFSDagImport(r, fixtureCid) + assert.NoError(t, err) + + t.Run("Succeeds Fetching Range", func(t *testing.T) { + t.Parallel() + + resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) { + r.Header.Set("Range", "bytes=1276-1279") + }) + assert.Equal(t, http.StatusPartialContent, resp.StatusCode) + assert.Equal(t, "bytes 1276-1279/109266405", resp.Headers.Get("Content-Range")) + assert.Equal(t, "iana", resp.Body) + }) + + t.Run("Succeeds Fetching Second Range", func(t *testing.T) { + t.Parallel() + + resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) { + r.Header.Set("Range", "bytes=29839070-29839080") + }) + assert.Equal(t, http.StatusPartialContent, resp.StatusCode) + assert.Equal(t, "bytes 29839070-29839080/109266405", resp.Headers.Get("Content-Range")) + assert.Equal(t, "EXAMPLE.COM", resp.Body) + }) + + t.Run("Succeeds Fetching First Range of Multi-range Request", func(t *testing.T) { + t.Parallel() + + resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) { + r.Header.Set("Range", "bytes=1276-1279, 29839070-29839080") + }) + assert.Equal(t, http.StatusPartialContent, resp.StatusCode) + assert.Equal(t, "bytes 1276-1279/109266405", resp.Headers.Get("Content-Range")) + assert.Equal(t, "iana", resp.Body) + }) +}