Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: multi range request considers servers that do not return multi range #113

Merged
merged 8 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- `--verbose` flag displays all the output to the console
- `Expect.Headers.ChecksAll`: an expectation to test all the header values (0, 1, or more)

### Changed
- finalized port of Kubo's sharness tests. [PR](https://github.com/ipfs/gateway-conformance/pull/92)
Expand Down
27 changes: 27 additions & 0 deletions fixtures/path_gateway_unixfs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,30 @@ ln -s foo testfiles/bar &&
ROOT_DIR_CID=$(ipfs add -Qr testfiles) &&
ipfs dag export $ROOT_DIR_CID > symlink.car
```

### [dir-with-files.car](./dir-with-files.car)

```sh
ipfs version
# ipfs version 0.21.0
TEXT=$(cat <<-EOF
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc non imperdiet nunc. Proin ac quam ut nibh eleifend aliquet. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed ligula dolor, imperdiet sagittis arcu et, semper tincidunt urna. Donec et tempor augue, quis sollicitudin metus. Curabitur semper ullamcorper aliquet. Mauris hendrerit sodales lectus eget fermentum. Proin sollicitudin vestibulum commodo. Vivamus nec lectus eu augue aliquet dignissim nec condimentum justo. In hac habitasse platea dictumst. Mauris vel sem neque.

Vivamus finibus, enim at lacinia semper, arcu erat gravida lacus, sit amet gravida magna orci sit amet est. Sed non leo lacus. Nullam viverra ipsum a tincidunt dapibus. Nulla pulvinar ligula sit amet ante ultrices tempus. Proin purus urna, semper sed lobortis quis, gravida vitae ipsum. Aliquam mi urna, pulvinar eu bibendum quis, convallis ac dolor. In gravida justo sed risus ullamcorper, vitae luctus massa hendrerit. Pellentesque habitant amet.
EOF
)

ASCII_CID=$(echo "hello application/vnd.ipld.car" | ipfs add --cid-version=1 -q)
HELLO_CID=$(echo "hello world" | ipfs add --cid-version=1 -q)
MULTIBLOCK_CID=$(echo -n $TEXT | ipfs add --cid-version=1 --chunker=size-256 -q)
# Print the Multiblock CIDs (required for some tests)
ipfs dag get $MULTIBLOCK_CID | jq .Links | jq -r '.[].Hash."/"'
ipfs files mkdir -p --cid-version 1 /dir-with-files
ipfs files cp /ipfs/$ASCII_CID /dir-with-files/ascii-copy.txt
ipfs files cp /ipfs/$ASCII_CID /dir-with-files/ascii.txt
ipfs files cp /ipfs/$HELLO_CID /dir-with-files/hello.txt
ipfs files cp /ipfs/$MULTIBLOCK_CID /dir-with-files/multiblock.txt
ipfs files ls -l
# Manually CID of "dir-with-files" and then...
ipfs dag export $CID
```
Binary file added fixtures/path_gateway_unixfs/dir-with-files.car
Binary file not shown.
66 changes: 0 additions & 66 deletions fixtures/t0123/README.md

This file was deleted.

23 changes: 4 additions & 19 deletions tests/path_gateway_raw_test.go
hacdias marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

"github.com/ipfs/gateway-conformance/tooling/car"
"github.com/ipfs/gateway-conformance/tooling/check"
"github.com/ipfs/gateway-conformance/tooling/specs"
. "github.com/ipfs/gateway-conformance/tooling/test"
)
Expand Down Expand Up @@ -45,25 +44,11 @@ func TestGatewayBlock(t *testing.T) {
),
Response: Expect().
Status(206).
Body(fixture.MustGetRawData("dir")[6:17]),
},
{
Name: "GET with application/vnd.ipld.raw with multiple range request includes correct bytes",
Request: Request().
Path("/ipfs/{{cid}}/dir/ascii.txt", fixture.MustGetCid()).
Headers(
Header("Accept", "application/vnd.ipld.raw"),
Header("Range", "bytes=6-16,0-4"),
),
Response: Expect().
Status(206).
Body(check.And(
check.Contains("Content-Range: bytes 6-16/31"),
check.Contains("Content-Type: application/vnd.ipld.raw"),
check.Contains("application"),
check.Contains("Content-Range: bytes 0-4/31"),
check.Contains("hello"),
)),
Header("Content-Type", "application/vnd.ipld.raw"),
Header("Content-Range", "bytes 6-16/57"),
).
Body(fixture.MustGetRawData("dir")[6:17]),
},
{
Name: "GET with application/vnd.ipld.raw header returns expected response headers",
Expand Down
123 changes: 123 additions & 0 deletions tests/path_gateway_unixfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,126 @@ func TestGatewaySymlink(t *testing.T) {

RunWithSpecs(t, tests, specs.PathGatewayUnixFS)
}

func TestGatewayUnixFSFileRanges(t *testing.T) {
// Multi-range requests MUST conform to the HTTP semantics. The server does not
// need to be able to support returning multiple ranges. However, it must respond
// correctly.
fixture := car.MustOpenUnixfsCar("path_gateway_unixfs/dir-with-files.car")

var (
contentType string
contentRange string
)

RunWithSpecs(t, SugarTests{
{
Name: "GET for /ipfs/ file with single range request includes correct bytes",
Request: Request().
Path("/ipfs/{{cid}}/ascii.txt", fixture.MustGetCid()).
Headers(
Header("Range", "bytes=6-16"),
),
Response: Expect().
Status(206).
Headers(
Header("Content-Type").Contains("text/plain"),
Header("Content-Range").Equals("bytes 6-16/31"),
).
Body(fixture.MustGetRawData("ascii.txt")[6:17]),
},
{
Name: "GET for /ipfs/ file with multiple range request includes correct bytes",
Request: Request().
Path("/ipfs/{{cid}}/ascii.txt", fixture.MustGetCid()).
Headers(
Header("Range", "bytes=6-16,0-4"),
),
Response: Expect().
Status(206).
Headers(
Header("Content-Type").
Checks(func(v string) bool {
contentType = v
return v != ""
}),
Header("Content-Range").
ChecksAll(func(v []string) bool {
if len(v) == 1 {
contentRange = v[0]
}
return true
}),
),
},
}, specs.PathGatewayRaw)

tests := SugarTests{}

if strings.Contains(contentType, "text/plain") {
// The server is not able to respond to a multi-range request. Therefore,
// there might be only one range or... just the whole file, depending on the headers.

if contentRange == "" {
// Server does not support range requests and must send back the complete file.
tests = append(tests, SugarTest{
Name: "GET for /ipfs/ file with multiple range request includes correct bytes",
Request: Request().
Path("/ipfs/{{cid}}/ascii.txt", fixture.MustGetCid()).
Headers(
Header("Range", "bytes=6-16,0-4"),
),
Response: Expect().
Status(206).
Headers(
Header("Content-Type").Contains("text/plain"),
Header("Content-Range").IsEmpty(),
).
Body(fixture.MustGetRawData("ascii.txt")),
})
} else {
// Server supports range requests but only the first range.
tests = append(tests, SugarTest{
Name: "GET for /ipfs/ file with multiple range request includes correct bytes",
Request: Request().
Path("/ipfs/{{cid}}/ascii.txt", fixture.MustGetCid()).
Headers(
Header("Range", "bytes=6-16,0-4"),
),
Response: Expect().
Status(206).
Headers(
Header("Content-Type").Contains("text/plain"),
Header("Content-Range", "bytes 6-16/31"),
).
Body(fixture.MustGetRawData("ascii.txt")[6:17]),
})
}
} else if strings.Contains(contentType, "multipart/byteranges") {
// The server supports responding with multi-range requests.
tests = append(tests, SugarTest{
Name: "GET for /ipfs/ file with multiple range request includes correct bytes",
Request: Request().
Path("/ipfs/{{cid}}/ascii.txt", fixture.MustGetCid()).
Headers(
Header("Range", "bytes=6-16,0-4"),
),
Response: Expect().
Status(206).
Headers(
Header("Content-Type").Contains("multipart/byteranges"),
).
Body(And(
Contains("Content-Range: bytes 6-16/31"),
Contains("Content-Type: text/plain"),
Contains(string(fixture.MustGetRawData("ascii.txt")[6:17])),
Contains("Content-Range: bytes 0-4/31"),
Contains(string(fixture.MustGetRawData("ascii.txt")[0:5])),
)),
})
} else {
t.Error("Content-Type header did not match any of the accepted options")
}

RunWithSpecs(t, tests, specs.PathGatewayUnixFS)
}
Loading
Loading