Skip to content

Commit

Permalink
api: Add support for Range header in object GET requests
Browse files Browse the repository at this point in the history
The `Range` header is now accepted for `/objects/{cid}/by_id/{oid}` and
`/objects/{cid}/by_attribute/{oid}` requests.

Close #224.

Signed-off-by: Tatiana Nesterenko <[email protected]>
  • Loading branch information
tatiana-nspcc committed Aug 23, 2024
1 parent 996a8da commit fae80c6
Show file tree
Hide file tree
Showing 6 changed files with 848 additions and 148 deletions.
41 changes: 34 additions & 7 deletions cmd/neofs-rest-gw/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,15 @@ func runTests(ctx context.Context, t *testing.T, key *keys.PrivateKey, node stri
t.Run("rest new head object with wallet connect", func(t *testing.T) { restNewObjectHead(ctx, t, clientPool, &owner, cnrID, signer, true) })
t.Run("rest new head by attribute", func(t *testing.T) { restNewObjectHeadByAttribute(ctx, t, clientPool, &owner, cnrID, signer, false) })
t.Run("rest new head by attribute with wallet connect", func(t *testing.T) { restNewObjectHeadByAttribute(ctx, t, clientPool, &owner, cnrID, signer, true) })
t.Run("rest new get by attribute", func(t *testing.T) { restNewObjectGetByAttribute(ctx, t, clientPool, &owner, cnrID, signer, false) })
t.Run("rest new get by attribute with wallet connect", func(t *testing.T) { restNewObjectGetByAttribute(ctx, t, clientPool, &owner, cnrID, signer, true) })
t.Run("rest new get by attribute", func(t *testing.T) {
restNewObjectGetByAttribute(ctx, t, clientPool, &owner, cnrID, signer, false, false)
})
t.Run("rest new get by attribute with wallet connect", func(t *testing.T) {
restNewObjectGetByAttribute(ctx, t, clientPool, &owner, cnrID, signer, true, false)
})
t.Run("rest new get by attribute with range", func(t *testing.T) {
restNewObjectGetByAttribute(ctx, t, clientPool, &owner, cnrID, signer, false, true)
})
}

func createDockerContainer(ctx context.Context, t *testing.T, image, version string) testcontainers.Container {
Expand Down Expand Up @@ -2278,11 +2285,13 @@ func restNewObjectHeadByAttribute(ctx context.Context, t *testing.T, p *pool.Poo
})
}

func restNewObjectGetByAttribute(ctx context.Context, t *testing.T, p *pool.Pool, ownerID *user.ID, cnrID cid.ID, signer user.Signer, walletConnect bool) {
func restNewObjectGetByAttribute(ctx context.Context, t *testing.T, p *pool.Pool, ownerID *user.ID, cnrID cid.ID, signer user.Signer, walletConnect, addRange bool) {
bearer := apiserver.Bearer{
Object: []apiserver.Record{
formAllowRecord(apiserver.OperationGET),
formAllowRecord(apiserver.OperationSEARCH),
formAllowRecord(apiserver.OperationHEAD),
formAllowRecord(apiserver.OperationRANGE),
},
}
bearer.Object = append(bearer.Object, getRestrictBearerRecords()...)
Expand All @@ -2304,7 +2313,7 @@ func restNewObjectGetByAttribute(ctx context.Context, t *testing.T, p *pool.Pool

var (
content = []byte("some content")
fileNameAttr = "new-get-obj-by-attr-name-" + strconv.FormatBool(walletConnect)
fileNameAttr = "new-get-obj-by-attr-name-" + strconv.FormatBool(walletConnect) + strconv.FormatBool(addRange)
createTS = time.Now().Unix()
attrKey = "user-attribute"
attrValue = "user value"
Expand Down Expand Up @@ -2333,7 +2342,15 @@ func restNewObjectGetByAttribute(ctx context.Context, t *testing.T, p *pool.Pool
prepareCommonHeaders(request.Header, bearerToken)
}

headers, rawPayload := doRequest(t, httpClient, request, http.StatusOK, nil)
start, end := 5, 10
status := http.StatusOK
if addRange {
request.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, end))
status = http.StatusPartialContent
}

headers, rawPayload := doRequest(t, httpClient, request, status, nil)

require.NotEmpty(t, headers)

for key, vals := range headers {
Expand All @@ -2358,7 +2375,11 @@ func restNewObjectGetByAttribute(ctx context.Context, t *testing.T, p *pool.Pool
case "X-Container-Id":
require.Equal(t, cnrID.String(), vals[0])
case "Content-Length":
require.Equal(t, strconv.FormatInt(int64(len(content)), 10), vals[0])
if addRange {
require.Equal(t, strconv.Itoa(end-start+1), vals[0])
} else {
require.Equal(t, strconv.Itoa(len(content)), vals[0])
}
case "Content-Type":
require.Equal(t, "text/plain; charset=utf-8", vals[0])
case "Date":
Expand All @@ -2367,10 +2388,16 @@ func restNewObjectGetByAttribute(ctx context.Context, t *testing.T, p *pool.Pool
require.GreaterOrEqual(t, tm.Unix(), createTS)
case "Access-Control-Allow-Origin":
require.Equal(t, "*", vals[0])
case "Content-Range":
require.Equal(t, fmt.Sprintf("bytes %d-%d/%d", start, end, len(content)), vals[0])
}
}

require.Equal(t, content, rawPayload)
if addRange {
require.Equal(t, content[start:end+1], rawPayload)
} else {
require.Equal(t, content, rawPayload)
}
})
}

Expand Down
Loading

0 comments on commit fae80c6

Please sign in to comment.