Skip to content

Commit 89b06cd

Browse files
committed
Document Conditional Requests
Signed-off-by: Jon Johnson <[email protected]>
1 parent e734841 commit 89b06cd

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

preconditions.md

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## Conditional Requests
2+
3+
The [Distribution Specification](spec.md) describes mutable tag identifiers, which can be used when pushing, pulling, and deleting manifests.
4+
Given that HTTP is a stateless protocol for distributed systems, the mutability of tag references leads to many possible race conditions.
5+
Fortunately, HTTP has a mechanism for dealing with race conditions: conditional requests.
6+
7+
[RFC 7232](https://tools.ietf.org/html/rfc7232) defines the semantics of Conditional Requests in great detail, so this document will simply highlight the relevant portions of the RFC as applied to the Distribution Specification.
8+
9+
### Safely Mutating Manifests
10+
11+
The `If-Match` header from [section 3.1](https://tools.ietf.org/html/rfc7232#section-3.1):
12+
13+
> makes the request method conditional on
14+
> the recipient origin server either having at least one current
15+
> representation of the target resource, when the field-value is "\*",
16+
> or having a current representation of the target resource that has an
17+
> entity-tag matching a member of the list of entity-tags provided in
18+
> the field-value.
19+
20+
Specifically interesting for mutating manifests:
21+
22+
> If-Match is most often used with state-changing methods (e.g., POST,
23+
> PUT, DELETE) to prevent accidental overwrites when multiple user
24+
> agents might be acting in parallel on the same resource (i.e., to
25+
> prevent the "lost update" problem). It can also be used with safe
26+
> methods to abort a request if the selected representation does not
27+
> match one already stored (or partially stored) from a prior request.
28+
29+
A client wishing to safely mutate a manifest SHOULD include in the manifest PUT request the following header:
30+
31+
```
32+
If-Match: "<ETag>"
33+
```
34+
35+
Where `<ETag>` is the entity-tag that matches the representation of the manifest as expected by the client, i.e. the header returned by the registry, as described in [section 2.3](https://tools.ietf.org/html/rfc7232#section-2.3):
36+
37+
> The "ETag" header field in a response provides the current entity-tag
38+
> for the selected representation, as determined at the conclusion of
39+
> handling the request. An entity-tag is an opaque validator for
40+
> differentiating between multiple representations of the same
41+
> resource, regardless of whether those multiple representations are
42+
> due to resource state changes over time, content negotiation
43+
> resulting in multiple representations being valid at the same time,
44+
> or both. An entity-tag consists of an opaque quoted string, possibly
45+
> prefixed by a weakness indicator.
46+
47+
If the state of the manifest in the registry does not match the supplied ETag, the registry MUST return a `412 Precondition Failed` response.
48+
49+
### Avoiding Overwriting Tags
50+
51+
The `If-None-Match` header from [section 3.2](https://tools.ietf.org/html/rfc7232#section-3.2):
52+
53+
> makes the request method conditional
54+
> on a recipient cache or origin server either not having any current
55+
> representation of the target resource, when the field-value is "\*",
56+
> or having a selected representation with an entity-tag that does not
57+
> match any of those listed in the field-value
58+
59+
Specifically interesting for avoiding tag overwriting:
60+
61+
> If-None-Match can also be used with a value of "\*" to prevent an
62+
> unsafe request method (e.g., PUT) from inadvertently modifying an
63+
> existing representation of the target resource when the client
64+
> believes that the resource does not have a current representation
65+
> (Section 4.2.1 of [RFC7231]). This is a variation on the "lost
66+
> update" problem that might arise if more than one client attempts to
67+
> create an initial representation for the target resource.
68+
69+
A client wishing to avoid overwriting any existing tags SHOULD include in the manifest PUT request the following header:
70+
71+
```
72+
If-None-Match: *
73+
```
74+
75+
If there already exists a manifest in the registry with a matching tag identifier, the registry MUST return a `412 Precondition Failed` response.

spec.md

+5
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ When process B attempts to upload the layer, the registry indicates that its not
100100
If process A and B upload the same layer at the same time, both operations will proceed and the first to complete will be stored in the registry.
101101
Even in the case where both uploads are accepted, the registry may securely only store one copy of the layer since the computed digests match.
102102

103+
### Conditional Requests
104+
105+
A container engine would like to safely push a new tag or modify an existing tag without racing against another container engine acting upon the registry at the same time.
106+
Registries and clients MAY rely on [conditional request](./preconditions.md) semantics to avoid race conditions in the face of concurrent mutations.
107+
103108
## Conformance
104109

105110
For more information on testing for conformance, please see the [conformance README](./conformance/README.md)

0 commit comments

Comments
 (0)