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

DRS bundle contents pagination #367

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions openapi/components/parameters/ContentsPage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
in: query
name: page
schema:
type: integer
example: 5
description: >-
For paginated traversal of the `contents` array of a DRS Object bundle. Indicates the requested "page" or subset of `contents` objects.
54 changes: 54 additions & 0 deletions openapi/components/responses/200OkContentsArray.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
description: The `contents` array for the requested `DrsObject` was returned successfully
headers:
Link:
description: |
Pagination links to retrieve the `contents` array of a DRS Object bundle via paginated traversal.

#### Link header structure

The value of the `Link` header is a **comma-delimited** list of entries. Each entry in the list contains:
1. A URL that clients can request to obtain a new subset of `contents` for the same DRS Object
2. A `rel` (relation) keyword, indicating the direction of traversal (e.g. next page, previous page, etc.)

The correct format for a pagination link is as follows:

`<{url}>; rel="{rel_keyword}"`

i.e.:
* The URL must be encapsulated in angle brackets
* The `rel` keyword must be preceded by an explicit `rel=` indicator and encapsulated in double quotes
* The URL and `rel` keyword must be separated by `; `

#### `rel` keywords

Standardized `rel` keywords inform the client of the traversal direction of each URL in the `Link` header, enabling dynamic traversal. The following table outlines the acceptable `rel` keywords and what they mean:

| `rel` keyword | description |
|-------------|-------------|
| next | URL retrieves the next page of `contents` objects compared to the current page the client is on |
| prev | URL retrieves the previous page of `contents` objects compared to the current page the client is on |
| first | URL jumps to the first page of `contents` objects |
| last | URL jumps to the final page of `contents` objects |

Only `rel="next"` links are mandatory for unidirectional traversal. The other `rel` links are optional, and can be left up to individual implementers if they wish to enable multidirectional traversal for their DRS service.

#### Example Link header

The following snippet displays an example `Link` header value for paginated traversal. In the example, the client most recently obtained page `14` of `contents` objects for the DRS Object with an ID of `314159`, out of a total `34` pages.

```
Link: <https://drs.example.org/ga4gh/drs/v1/objects/314159/contents?page=15>; rel="next",
<https://drs.example.org/ga4gh/drs/v1/objects/314159/contents?page=34>; rel="last",
<https://drs.example.org/ga4gh/drs/v1/objects/314159/contents?page=1>; rel="first",
<https://drs.example.org/ga4gh/drs/v1/objects/314159/contents?page=13>; rel="prev"
```

**Note:** Pagination in DRS is modeled after [Github's approach and documentation](https://docs.github.com/en/rest/guides/traversing-with-pagination).
schema:
type: string
content:
application/json:
schema:
type: array
items:
$ref: '../schemas/ContentsObject.yaml'
2 changes: 2 additions & 0 deletions openapi/data_repository_service.openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ paths:
$ref: ./paths/objects@{object_id}.yaml
/objects/{object_id}/access/{access_id}:
$ref: ./paths/objects@{object_id}@access@{access_id}.yaml
/objects/{object_id}/contents:
$ref: ./paths/objects@{object_id}@contents.yaml
components:
securitySchemes:
BasicAuth:
Expand Down
11 changes: 6 additions & 5 deletions openapi/paths/objects@{object_id}.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ post:

Method is a POST to accomodate a JWT GA4GH Passport sent in the formData in order to authorize access.
operationId: PostObject
parameters:
- $ref: '../components/parameters/ObjectId.yaml'
requestBody:
$ref: '../components/requestBodies/PostObjectBody.yaml'
security:
- PassportAuth: []
responses:
200:
$ref: '../components/responses/200OkAccess.yaml'
$ref: '../components/responses/200OkDrsObject.yaml'
202:
$ref: '../components/responses/202Accepted.yaml'
400:
Expand All @@ -52,7 +56,4 @@ post:
tags:
- Objects
x-swagger-router-controller: ga4gh.drs.server
parameters:
- $ref: '../components/parameters/ObjectId.yaml'
requestBody:
$ref: '../components/requestBodies/PostObjectBody.yaml'

65 changes: 65 additions & 0 deletions openapi/paths/objects@{object_id}@contents.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
get:
summary: Get contents array of a DrsObject bundle
description: >-
Returns the `contents` array of a DrsObject bundle. Large arrays may be
paginated for efficient transfer, in which case, a `Link` header will be
provided to support client page traversal.
operationId: GetObjectContents
parameters:
- $ref: '../components/parameters/ObjectId.yaml'
- $ref: '../components/parameters/Expand.yaml'
- $ref: '../components/parameters/ContentsPage.yaml'
responses:
200:
$ref: '../components/responses/200OkContentsArray.yaml'
202:
$ref: '../components/responses/202Accepted.yaml'
400:
$ref: '../components/responses/400BadRequest.yaml'
401:
$ref: '../components/responses/401Unauthorized.yaml'
403:
$ref: '../components/responses/403Forbidden.yaml'
404:
$ref: '../components/responses/404NotFoundDrsObject.yaml'
500:
$ref: '../components/responses/500InternalServerError.yaml'
tags:
- Objects
x-swagger-router-controller: ga4gh.drs.server

post:
summary: Get contents array of a DrsObject bundle
description: >-
Returns the `contents` array of a DrsObject bundle. Large arrays may be
paginated for efficient transfer, in which case, a `Link` header will be
provided to support client page traversal.

POST method accomodates JWT GA4GH Passport sent in the request body in order
to authorize access.
operationId: GetObjectContentsPost
parameters:
- $ref: '../components/parameters/ObjectId.yaml'
- $ref: '../components/parameters/ContentsPage.yaml'
requestBody:
$ref: '../components/requestBodies/PostObjectBody.yaml'
security:
- PassportAuth: []
responses:
200:
$ref: '../components/responses/200OkContentsArray.yaml'
202:
$ref: '../components/responses/202Accepted.yaml'
400:
$ref: '../components/responses/400BadRequest.yaml'
401:
$ref: '../components/responses/401Unauthorized.yaml'
403:
$ref: '../components/responses/403Forbidden.yaml'
404:
$ref: '../components/responses/404NotFoundDrsObject.yaml'
500:
$ref: '../components/responses/500InternalServerError.yaml'
tags:
- Objects
x-swagger-router-controller: ga4gh.drs.server