forked from TrueCloudLab/distribution
Paginate catalog and tag results with Link header
Move the specification to use a Link header, rather than a "next" entry in the json results. This prevents requiring clients from parsing the request body to issue the next request. It also ensures that the returned response body does not change in between requests. The ordering of the specification has been slightly tweaked, as well. Listing image tags has been moved after the catalog specification. Tag pagination now heavily references catalog pagination. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
aebe850f73
commit
006214d902
3 changed files with 283 additions and 284 deletions
278
docs/spec/api.md
278
docs/spec/api.md
|
@ -754,7 +754,129 @@ each unknown blob. The response format is as follows:
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Listing Repositories
|
||||||
|
|
||||||
|
Images are stored in collections, known as a _repository_, which is keyed by a
|
||||||
|
`name`, as seen throughout the API specification. A registry instance may
|
||||||
|
contain several repositories. The list of available repositories is made
|
||||||
|
available through the _catalog_.
|
||||||
|
|
||||||
|
The catalog for a given registry can be retrived with the following request:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /v2/_catalog
|
||||||
|
```
|
||||||
|
|
||||||
|
The response will be in the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
<name>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the contents of the response are specific to the registry
|
||||||
|
implementation. Some registries may opt to provide a full catalog output,
|
||||||
|
limit it based on the user's access level or omit upstream results, if
|
||||||
|
providing mirroring functionality. Subsequently, the presence of a repository
|
||||||
|
in the catalog listing only means that the registry *may* provide access to
|
||||||
|
the repository at the time of the request. Conversely, a missing entry does
|
||||||
|
*not* mean that the registry does not have the repository. More succinctly,
|
||||||
|
the presence of a repository only guarantees that it is there but not that it
|
||||||
|
is _not_ there.
|
||||||
|
|
||||||
|
For registries with a large number of repositories, this response may be quite
|
||||||
|
large. If such a response is expected, one should use pagination.
|
||||||
|
|
||||||
|
#### Pagination
|
||||||
|
|
||||||
|
Paginated catalog results can be retrieved by adding an `n` parameter to the
|
||||||
|
request URL, declaring that the response should be limited to `n` results.
|
||||||
|
Starting a paginated flow begins as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /v2/_catalog?n=<integer>
|
||||||
|
```
|
||||||
|
|
||||||
|
The above specifies that a catalog response should be returned, from the start of
|
||||||
|
the result set, ordered lexically, limiting the number of results to `n`. The
|
||||||
|
response to such a request would look as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
Link: <<url>?n=<n from the request>&last=<last repository in response>>; rel="next"
|
||||||
|
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
<name>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The above includes the _first_ `n` entries from the result set. To get the
|
||||||
|
_next_ `n` entries, one can create a URL where the argument `last` has the
|
||||||
|
value from `repositories[len(repositories)-1]`. If there are indeed more
|
||||||
|
results, the URL for the next block is encoded in an
|
||||||
|
[RFC5988](https://tools.ietf.org/html/rfc5988) `Link` header, as a "next"
|
||||||
|
relation. The presence of the `Link` header communicates to the client that
|
||||||
|
the entire result set has not been returned and another request must be
|
||||||
|
issued. If the header is not present, the client can assume that all results
|
||||||
|
have been recieved.
|
||||||
|
|
||||||
|
> __NOTE:__ In the request template above, note that the brackets
|
||||||
|
> are required. For example, if the url is
|
||||||
|
> `http://example.com/v2/_catalog?n=20&last=b`, the value of the header would
|
||||||
|
> be `<http://example.com/v2/_catalog?n=20&last=b>; rel="next"`. Please see
|
||||||
|
> [RFC5988](https://tools.ietf.org/html/rfc5988) for details.
|
||||||
|
|
||||||
|
Compliant client implementations should always use the `Link` header
|
||||||
|
value when proceeding through results linearly. The client may construct URLs
|
||||||
|
to skip forward in the catalog.
|
||||||
|
|
||||||
|
To get the next result set, a client would issue the request as follows, using
|
||||||
|
the URL encoded in the described `Link` header:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /v2/_catalog?n=<n from the request>&last=<last repostory value from previous response>
|
||||||
|
```
|
||||||
|
|
||||||
|
The above process should then be repeated until the `Link` header is no longer
|
||||||
|
set.
|
||||||
|
|
||||||
|
The catalog result set is represented abstractly as a lexically sorted list,
|
||||||
|
where the position in that list can be specified by the query term `last`. The
|
||||||
|
entries in the response start _after_ the term specified by `last`, up to `n`
|
||||||
|
entries.
|
||||||
|
|
||||||
|
The behavior of `last` is quite simple when demonstrated with an example. Let
|
||||||
|
us say the registry has the following repositories:
|
||||||
|
|
||||||
|
```
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
```
|
||||||
|
|
||||||
|
If the value of `n` is 2, _a_ and _b_ will be returned on the first response.
|
||||||
|
The `Link` header returned on the response will have `n` set to 2 and last set
|
||||||
|
to _b_:
|
||||||
|
|
||||||
|
```
|
||||||
|
Link: <<url>?n=2&last=b>; rel="next"
|
||||||
|
```
|
||||||
|
|
||||||
|
The client can then issue the request with above value from the `Link` header,
|
||||||
|
receiving the values _c_ and _d_. Note that n may change on second to last
|
||||||
|
response or be omitted fully, if the server may so choose.
|
||||||
|
|
||||||
### Listing Image Tags
|
### Listing Image Tags
|
||||||
|
|
||||||
|
@ -781,8 +903,12 @@ large. If such a response is expected, one should use the pagination.
|
||||||
|
|
||||||
#### Pagination
|
#### Pagination
|
||||||
|
|
||||||
Paginated tag results can be retrieved by adding the appropriate pagination
|
Paginated tag results can be retrieved by adding the appropriate parameters to
|
||||||
parameters. Starting a paginated flow may begin as follows:
|
the request URL described above. The behavior of tag pagination is identical
|
||||||
|
to that specified for catalog pagination. We cover a simple flow to highlight
|
||||||
|
any differences.
|
||||||
|
|
||||||
|
Starting a paginated flow may begin as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /v2/<name>/tags/list?n=<integer>
|
GET /v2/<name>/tags/list?n=<integer>
|
||||||
|
@ -795,6 +921,7 @@ response to such a request would look as follows:
|
||||||
```
|
```
|
||||||
200 OK
|
200 OK
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
Link: <<url>?n=<n from the request>&last=<last tag value from previous response>>; rel="next"
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": <name>,
|
"name": <name>,
|
||||||
|
@ -802,141 +929,21 @@ Content-Type: application/json
|
||||||
<tag>,
|
<tag>,
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
"next": <url>?n=<n from the request>&last=<last tag value from previous response>
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> __TODO(stevvooe):__ Consider using a Header here, rather than a body parameter. A
|
|
||||||
header would allow one to issue the next request before parsing the response
|
|
||||||
body.
|
|
||||||
|
|
||||||
To get the next result set, a client would issue the request as follows, using
|
To get the next result set, a client would issue the request as follows, using
|
||||||
the value of "next" from the response body:
|
the value encoded in the [RFC5988](https://tools.ietf.org/html/rfc5988) `Link`
|
||||||
|
header:
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /v2/<name>/tags/list?n=<n from the request>&last=<last tag value from previous response>
|
GET /v2/<name>/tags/list?n=<n from the request>&last=<last tag value from previous response>
|
||||||
```
|
```
|
||||||
|
|
||||||
The above process should then be repeated until the `next` parameter is no
|
The above process should then be repeated until the `Link` header is no longer
|
||||||
longer set in the response.
|
set in the response. The behavior of the `last` parameter, the provided
|
||||||
|
response result, lexical ordering and encoding of the `Link` header are
|
||||||
The behavior of `last` is quite simple and can be demonstrated with an
|
identical to that of catalog pagination.
|
||||||
example. Let's say the repository has the following tags:
|
|
||||||
|
|
||||||
```
|
|
||||||
a
|
|
||||||
b
|
|
||||||
c
|
|
||||||
d
|
|
||||||
```
|
|
||||||
|
|
||||||
If the value of `n` is 2, _a_ and _b_ will be returned on the first response.
|
|
||||||
The `next` url within the respone will have `n` set to 2 and last set to _b_:
|
|
||||||
|
|
||||||
```
|
|
||||||
"next": <url>?n=2&last=b
|
|
||||||
```
|
|
||||||
|
|
||||||
The client can then issue the response, receiving the values _c_ and _d_. Note
|
|
||||||
that n may change on second to last response or be omitted fully, if the
|
|
||||||
server may so choose.
|
|
||||||
|
|
||||||
### Listing Repositories
|
|
||||||
|
|
||||||
Images are stored in collections, known as a _repository_, which is keyed by a
|
|
||||||
`name`, as seen throughout the API specification. A registry instance may
|
|
||||||
contain several repositories. The list of available repositories, or image
|
|
||||||
names, is made available through the _catalog_.
|
|
||||||
|
|
||||||
The catalog for a given registry can be retrived with the following request:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /v2/_catalog
|
|
||||||
```
|
|
||||||
|
|
||||||
The response will be in the following format:
|
|
||||||
|
|
||||||
```
|
|
||||||
200 OK
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"repositories": [
|
|
||||||
<name>,
|
|
||||||
...
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For registries with a large number of repositories, this response may be quite
|
|
||||||
large. If such a response is expected, one should use the pagination.
|
|
||||||
|
|
||||||
#### Pagination
|
|
||||||
|
|
||||||
Paginated repository results can be retrieved by adding the appropriate
|
|
||||||
pagination parameters, which are similar to those available in the tag API.
|
|
||||||
Starting a paginated flow may begin as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /v2/_catalog?n=<integer>
|
|
||||||
```
|
|
||||||
|
|
||||||
The above specifies that a catalog response should be returned, from the start of
|
|
||||||
the result set, ordered lexically, limiting the number of results to `n`. The
|
|
||||||
response to such a request would look as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
200 OK
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"repositories": [
|
|
||||||
<name>,
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"next": <url>?n=<n from the request>&last=<last repository value from previous response>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
> __TODO(stevvooe):__ Consider using a Header here, rather than a body parameter. A
|
|
||||||
header would allow one to issue the next request before parsing the response
|
|
||||||
body.
|
|
||||||
|
|
||||||
To get the next result set, a client would issue the request as follows, using
|
|
||||||
the value of "next" from the response body:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /v2/_catalog?n=<n from the request>&last=<last repostory value from previous response>
|
|
||||||
```
|
|
||||||
|
|
||||||
The above process should then be repeated until the `next` parameter is no
|
|
||||||
longer set in the response.
|
|
||||||
|
|
||||||
The result set of repository names is represented abstractly as a lexically
|
|
||||||
sorted list, where the position in that list can be specified by the query
|
|
||||||
term `last`. The entries in the response start _after_ the term specified by
|
|
||||||
`last`, up to `n` entries.
|
|
||||||
|
|
||||||
The behavior of `last` is quite simple when demonstrated with an example.
|
|
||||||
Let's say the registry has the following repositories:
|
|
||||||
|
|
||||||
```
|
|
||||||
a
|
|
||||||
b
|
|
||||||
c
|
|
||||||
d
|
|
||||||
```
|
|
||||||
|
|
||||||
If the value of `n` is 2, _a_ and _b_ will be returned on the first response.
|
|
||||||
The `next` url within the respone will have `n` set to 2 and last set to _b_:
|
|
||||||
|
|
||||||
```
|
|
||||||
"next": <url>?n=2&last=b
|
|
||||||
```
|
|
||||||
|
|
||||||
The client can then issue the request with above value of `next`, receiving
|
|
||||||
the values _c_ and _d_. Note that n may change on second to last response or
|
|
||||||
be omitted fully, if the server may so choose.
|
|
||||||
|
|
||||||
### Deleting an Image
|
### Deleting an Image
|
||||||
|
|
||||||
|
@ -1142,6 +1149,7 @@ The following parameters should be specified on the request:
|
||||||
```
|
```
|
||||||
200 OK
|
200 OK
|
||||||
Content-Length: <length>
|
Content-Length: <length>
|
||||||
|
Link: <<url>?n=<last n value>&last=<last entry from response>>; rel="next"
|
||||||
Content-Type: application/json; charset=utf-8
|
Content-Type: application/json; charset=utf-8
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1256,22 +1264,17 @@ Content-Type: application/json; charset=utf-8
|
||||||
<tag>,
|
<tag>,
|
||||||
...
|
...
|
||||||
],
|
],
|
||||||
"next": "<url>?last=<name>&n=<last value of n>"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A list of tags for the named repository.
|
A list of tags for the named repository.
|
||||||
The following fields may be returned in the response body:
|
|
||||||
|
|
||||||
|Name|Description|
|
|
||||||
|----|-----------|
|
|
||||||
|`next`|Provides the URL to get the next set of results, if available.|
|
|
||||||
|
|
||||||
The following headers will be returned with the response:
|
The following headers will be returned with the response:
|
||||||
|
|
||||||
|Name|Description|
|
|Name|Description|
|
||||||
|----|-----------|
|
|----|-----------|
|
||||||
|`Content-Length`|Length of the JSON response body.|
|
|`Content-Length`|Length of the JSON response body.|
|
||||||
|
|`Link`|RFC5988 compliant rel='next' with URL to next result set, if available|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3154,6 +3157,7 @@ Request an unabridged list of repositories available.
|
||||||
```
|
```
|
||||||
200 OK
|
200 OK
|
||||||
Content-Length: <length>
|
Content-Length: <length>
|
||||||
|
Link: <<url>?n=<last n value>&last=<last entry from response>>; rel="next"
|
||||||
Content-Type: application/json; charset=utf-8
|
Content-Type: application/json; charset=utf-8
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -3210,17 +3214,13 @@ Content-Type: application/json; charset=utf-8
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
The following fields may be returned in the response body:
|
|
||||||
|
|
||||||
|Name|Description|
|
|
||||||
|----|-----------|
|
|
||||||
|`next`|Provides the URL to get the next set of results, if available.|
|
|
||||||
|
|
||||||
The following headers will be returned with the response:
|
The following headers will be returned with the response:
|
||||||
|
|
||||||
|Name|Description|
|
|Name|Description|
|
||||||
|----|-----------|
|
|----|-----------|
|
||||||
|`Content-Length`|Length of the JSON response body.|
|
|`Content-Length`|Length of the JSON response body.|
|
||||||
|
|`Link`|RFC5988 compliant rel='next' with URL to next result set, if available|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -754,7 +754,129 @@ each unknown blob. The response format is as follows:
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Listing Repositories
|
||||||
|
|
||||||
|
Images are stored in collections, known as a _repository_, which is keyed by a
|
||||||
|
`name`, as seen throughout the API specification. A registry instance may
|
||||||
|
contain several repositories. The list of available repositories is made
|
||||||
|
available through the _catalog_.
|
||||||
|
|
||||||
|
The catalog for a given registry can be retrived with the following request:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /v2/_catalog
|
||||||
|
```
|
||||||
|
|
||||||
|
The response will be in the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
<name>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the contents of the response are specific to the registry
|
||||||
|
implementation. Some registries may opt to provide a full catalog output,
|
||||||
|
limit it based on the user's access level or omit upstream results, if
|
||||||
|
providing mirroring functionality. Subsequently, the presence of a repository
|
||||||
|
in the catalog listing only means that the registry *may* provide access to
|
||||||
|
the repository at the time of the request. Conversely, a missing entry does
|
||||||
|
*not* mean that the registry does not have the repository. More succinctly,
|
||||||
|
the presence of a repository only guarantees that it is there but not that it
|
||||||
|
is _not_ there.
|
||||||
|
|
||||||
|
For registries with a large number of repositories, this response may be quite
|
||||||
|
large. If such a response is expected, one should use pagination.
|
||||||
|
|
||||||
|
#### Pagination
|
||||||
|
|
||||||
|
Paginated catalog results can be retrieved by adding an `n` parameter to the
|
||||||
|
request URL, declaring that the response should be limited to `n` results.
|
||||||
|
Starting a paginated flow begins as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /v2/_catalog?n=<integer>
|
||||||
|
```
|
||||||
|
|
||||||
|
The above specifies that a catalog response should be returned, from the start of
|
||||||
|
the result set, ordered lexically, limiting the number of results to `n`. The
|
||||||
|
response to such a request would look as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
Link: <<url>?n=<n from the request>&last=<last repository in response>>; rel="next"
|
||||||
|
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
<name>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The above includes the _first_ `n` entries from the result set. To get the
|
||||||
|
_next_ `n` entries, one can create a URL where the argument `last` has the
|
||||||
|
value from `repositories[len(repositories)-1]`. If there are indeed more
|
||||||
|
results, the URL for the next block is encoded in an
|
||||||
|
[RFC5988](https://tools.ietf.org/html/rfc5988) `Link` header, as a "next"
|
||||||
|
relation. The presence of the `Link` header communicates to the client that
|
||||||
|
the entire result set has not been returned and another request must be
|
||||||
|
issued. If the header is not present, the client can assume that all results
|
||||||
|
have been recieved.
|
||||||
|
|
||||||
|
> __NOTE:__ In the request template above, note that the brackets
|
||||||
|
> are required. For example, if the url is
|
||||||
|
> `http://example.com/v2/_catalog?n=20&last=b`, the value of the header would
|
||||||
|
> be `<http://example.com/v2/_catalog?n=20&last=b>; rel="next"`. Please see
|
||||||
|
> [RFC5988](https://tools.ietf.org/html/rfc5988) for details.
|
||||||
|
|
||||||
|
Compliant client implementations should always use the `Link` header
|
||||||
|
value when proceeding through results linearly. The client may construct URLs
|
||||||
|
to skip forward in the catalog.
|
||||||
|
|
||||||
|
To get the next result set, a client would issue the request as follows, using
|
||||||
|
the URL encoded in the described `Link` header:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /v2/_catalog?n=<n from the request>&last=<last repostory value from previous response>
|
||||||
|
```
|
||||||
|
|
||||||
|
The above process should then be repeated until the `Link` header is no longer
|
||||||
|
set.
|
||||||
|
|
||||||
|
The catalog result set is represented abstractly as a lexically sorted list,
|
||||||
|
where the position in that list can be specified by the query term `last`. The
|
||||||
|
entries in the response start _after_ the term specified by `last`, up to `n`
|
||||||
|
entries.
|
||||||
|
|
||||||
|
The behavior of `last` is quite simple when demonstrated with an example. Let
|
||||||
|
us say the registry has the following repositories:
|
||||||
|
|
||||||
|
```
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
```
|
||||||
|
|
||||||
|
If the value of `n` is 2, _a_ and _b_ will be returned on the first response.
|
||||||
|
The `Link` header returned on the response will have `n` set to 2 and last set
|
||||||
|
to _b_:
|
||||||
|
|
||||||
|
```
|
||||||
|
Link: <<url>?n=2&last=b>; rel="next"
|
||||||
|
```
|
||||||
|
|
||||||
|
The client can then issue the request with above value from the `Link` header,
|
||||||
|
receiving the values _c_ and _d_. Note that n may change on second to last
|
||||||
|
response or be omitted fully, if the server may so choose.
|
||||||
|
|
||||||
### Listing Image Tags
|
### Listing Image Tags
|
||||||
|
|
||||||
|
@ -781,8 +903,12 @@ large. If such a response is expected, one should use the pagination.
|
||||||
|
|
||||||
#### Pagination
|
#### Pagination
|
||||||
|
|
||||||
Paginated tag results can be retrieved by adding the appropriate pagination
|
Paginated tag results can be retrieved by adding the appropriate parameters to
|
||||||
parameters. Starting a paginated flow may begin as follows:
|
the request URL described above. The behavior of tag pagination is identical
|
||||||
|
to that specified for catalog pagination. We cover a simple flow to highlight
|
||||||
|
any differences.
|
||||||
|
|
||||||
|
Starting a paginated flow may begin as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /v2/<name>/tags/list?n=<integer>
|
GET /v2/<name>/tags/list?n=<integer>
|
||||||
|
@ -795,6 +921,7 @@ response to such a request would look as follows:
|
||||||
```
|
```
|
||||||
200 OK
|
200 OK
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
Link: <<url>?n=<n from the request>&last=<last tag value from previous response>>; rel="next"
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": <name>,
|
"name": <name>,
|
||||||
|
@ -802,141 +929,21 @@ Content-Type: application/json
|
||||||
<tag>,
|
<tag>,
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
"next": <url>?n=<n from the request>&last=<last tag value from previous response>
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> __TODO(stevvooe):__ Consider using a Header here, rather than a body parameter. A
|
|
||||||
header would allow one to issue the next request before parsing the response
|
|
||||||
body.
|
|
||||||
|
|
||||||
To get the next result set, a client would issue the request as follows, using
|
To get the next result set, a client would issue the request as follows, using
|
||||||
the value of "next" from the response body:
|
the value encoded in the [RFC5988](https://tools.ietf.org/html/rfc5988) `Link`
|
||||||
|
header:
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /v2/<name>/tags/list?n=<n from the request>&last=<last tag value from previous response>
|
GET /v2/<name>/tags/list?n=<n from the request>&last=<last tag value from previous response>
|
||||||
```
|
```
|
||||||
|
|
||||||
The above process should then be repeated until the `next` parameter is no
|
The above process should then be repeated until the `Link` header is no longer
|
||||||
longer set in the response.
|
set in the response. The behavior of the `last` parameter, the provided
|
||||||
|
response result, lexical ordering and encoding of the `Link` header are
|
||||||
The behavior of `last` is quite simple and can be demonstrated with an
|
identical to that of catalog pagination.
|
||||||
example. Let's say the repository has the following tags:
|
|
||||||
|
|
||||||
```
|
|
||||||
a
|
|
||||||
b
|
|
||||||
c
|
|
||||||
d
|
|
||||||
```
|
|
||||||
|
|
||||||
If the value of `n` is 2, _a_ and _b_ will be returned on the first response.
|
|
||||||
The `next` url within the respone will have `n` set to 2 and last set to _b_:
|
|
||||||
|
|
||||||
```
|
|
||||||
"next": <url>?n=2&last=b
|
|
||||||
```
|
|
||||||
|
|
||||||
The client can then issue the response, receiving the values _c_ and _d_. Note
|
|
||||||
that n may change on second to last response or be omitted fully, if the
|
|
||||||
server may so choose.
|
|
||||||
|
|
||||||
### Listing Repositories
|
|
||||||
|
|
||||||
Images are stored in collections, known as a _repository_, which is keyed by a
|
|
||||||
`name`, as seen throughout the API specification. A registry instance may
|
|
||||||
contain several repositories. The list of available repositories, or image
|
|
||||||
names, is made available through the _catalog_.
|
|
||||||
|
|
||||||
The catalog for a given registry can be retrived with the following request:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /v2/_catalog
|
|
||||||
```
|
|
||||||
|
|
||||||
The response will be in the following format:
|
|
||||||
|
|
||||||
```
|
|
||||||
200 OK
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"repositories": [
|
|
||||||
<name>,
|
|
||||||
...
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For registries with a large number of repositories, this response may be quite
|
|
||||||
large. If such a response is expected, one should use the pagination.
|
|
||||||
|
|
||||||
#### Pagination
|
|
||||||
|
|
||||||
Paginated repository results can be retrieved by adding the appropriate
|
|
||||||
pagination parameters, which are similar to those available in the tag API.
|
|
||||||
Starting a paginated flow may begin as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /v2/_catalog?n=<integer>
|
|
||||||
```
|
|
||||||
|
|
||||||
The above specifies that a catalog response should be returned, from the start of
|
|
||||||
the result set, ordered lexically, limiting the number of results to `n`. The
|
|
||||||
response to such a request would look as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
200 OK
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"repositories": [
|
|
||||||
<name>,
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"next": <url>?n=<n from the request>&last=<last repository value from previous response>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
> __TODO(stevvooe):__ Consider using a Header here, rather than a body parameter. A
|
|
||||||
header would allow one to issue the next request before parsing the response
|
|
||||||
body.
|
|
||||||
|
|
||||||
To get the next result set, a client would issue the request as follows, using
|
|
||||||
the value of "next" from the response body:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /v2/_catalog?n=<n from the request>&last=<last repostory value from previous response>
|
|
||||||
```
|
|
||||||
|
|
||||||
The above process should then be repeated until the `next` parameter is no
|
|
||||||
longer set in the response.
|
|
||||||
|
|
||||||
The result set of repository names is represented abstractly as a lexically
|
|
||||||
sorted list, where the position in that list can be specified by the query
|
|
||||||
term `last`. The entries in the response start _after_ the term specified by
|
|
||||||
`last`, up to `n` entries.
|
|
||||||
|
|
||||||
The behavior of `last` is quite simple when demonstrated with an example.
|
|
||||||
Let's say the registry has the following repositories:
|
|
||||||
|
|
||||||
```
|
|
||||||
a
|
|
||||||
b
|
|
||||||
c
|
|
||||||
d
|
|
||||||
```
|
|
||||||
|
|
||||||
If the value of `n` is 2, _a_ and _b_ will be returned on the first response.
|
|
||||||
The `next` url within the respone will have `n` set to 2 and last set to _b_:
|
|
||||||
|
|
||||||
```
|
|
||||||
"next": <url>?n=2&last=b
|
|
||||||
```
|
|
||||||
|
|
||||||
The client can then issue the request with above value of `next`, receiving
|
|
||||||
the values _c_ and _d_. Note that n may change on second to last response or
|
|
||||||
be omitted fully, if the server may so choose.
|
|
||||||
|
|
||||||
### Deleting an Image
|
### Deleting an Image
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,13 @@ var (
|
||||||
Format: "<digest>",
|
Format: "<digest>",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
linkHeader = ParameterDescriptor{
|
||||||
|
Name: "Link",
|
||||||
|
Type: "link",
|
||||||
|
Description: "RFC5988 compliant rel='next' with URL to next result set, if available",
|
||||||
|
Format: `<<url>?n=<last n value>&last=<last entry from response>>; rel="next"`,
|
||||||
|
}
|
||||||
|
|
||||||
paginationParameters = []ParameterDescriptor{
|
paginationParameters = []ParameterDescriptor{
|
||||||
{
|
{
|
||||||
Name: "n",
|
Name: "n",
|
||||||
|
@ -462,14 +469,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Description: "Length of the JSON response body.",
|
Description: "Length of the JSON response body.",
|
||||||
Format: "<length>",
|
Format: "<length>",
|
||||||
},
|
},
|
||||||
},
|
linkHeader,
|
||||||
Fields: []ParameterDescriptor{
|
|
||||||
{
|
|
||||||
Name: "next",
|
|
||||||
Type: "url",
|
|
||||||
Description: "Provides the URL to get the next set of results, if available.",
|
|
||||||
Format: "<url>",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Body: BodyDescriptor{
|
Body: BodyDescriptor{
|
||||||
ContentType: "application/json; charset=utf-8",
|
ContentType: "application/json; charset=utf-8",
|
||||||
|
@ -479,7 +479,6 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
<tag>,
|
<tag>,
|
||||||
...
|
...
|
||||||
],
|
],
|
||||||
"next": "<url>?last=<name>&n=<last value of n>"
|
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1439,14 +1438,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Description: "Length of the JSON response body.",
|
Description: "Length of the JSON response body.",
|
||||||
Format: "<length>",
|
Format: "<length>",
|
||||||
},
|
},
|
||||||
},
|
linkHeader,
|
||||||
Fields: []ParameterDescriptor{
|
|
||||||
{
|
|
||||||
Name: "next",
|
|
||||||
Type: "url",
|
|
||||||
Description: "Provides the URL to get the next set of results, if available.",
|
|
||||||
Format: "<url>",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue