Skip to content

Commit 353e9af

Browse files
author
Luke Sneeringer
authored
feat: AIP-154 – Resource freshness validation (#4)
1 parent 2564485 commit 353e9af

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

aip/general/0154/aip.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Resource freshness validation
2+
3+
APIs often need to validate that a client and server agree on the current state
4+
of a resource before taking some kind of action on that resource. For example,
5+
two processes updating the same resource in parallel could create a race
6+
condition, where the latter process "stomps over" the effort of the former one.
7+
8+
ETags provide a way to deal with this, by allowing the server to send a
9+
checksum based on the current content of a resource; when the client sends that
10+
checksum back, the server can ensure that the checksums match before acting on
11+
the request.
12+
13+
## Guidance
14+
15+
A resource **may** provide an `ETag` header when retrieving a single resource
16+
when it is important to ensure that the client has an up to date resource
17+
before acting on certain requests:
18+
19+
```
20+
200 OK
21+
Content-type: application/json
22+
ETag: "55cc0347-66fc-46c3-a26f-98a9a7d61d0e"
23+
```
24+
25+
The ETag **must** be provided by the server on output, and values **should**
26+
conform to [RFC 7232][]. Resources **must** support the `If-Match` header (and
27+
**may** support the `If-None-Match` header) if and only if resources provide
28+
the ETag.
29+
30+
**Note:** ETag values **must** include quotes as described in [RFC 7232][]. For
31+
example, a valid ETag is `"foo"`, not `foo`.
32+
33+
ETags **must** be based on an opaque checksum or hash of the resource that
34+
guarantees it will change if the resource changes.
35+
36+
### Condition headers
37+
38+
If the service receives a request to modify a resource that includes an
39+
`If-Match` header, the service **must** validate that the value matches the
40+
current ETag. If the `If-Match` header value does not match the ETag, the
41+
service **must** reply with an HTTP 412 error.
42+
43+
If the user omits the `If-Match` header, the service **should** permit the
44+
request. However, services with strong consistency or parallelism requirements
45+
**may** require users to send ETags all the time and reject the request with an
46+
HTTP 400 error if it does not contain an ETag.
47+
48+
If any conditional headers are supported for any operation within a service,
49+
the same conditional headers **must** be supported for all mutation methods
50+
(`POST`, `PATCH`, `PUT`, and `DELETE`) of any path that supports them, and
51+
**should** be supported uniformly for all operations across the service.
52+
53+
If any validator or conditional headers are supported for any operations in the
54+
service, the use of unsupported conditional headers **must** result in an
55+
error. (In other words, once a service gives the client reason to believe it
56+
understands conditional headers, it **must not** ever ignore them.)
57+
58+
### Read requests
59+
60+
If a service receives a `GET` or `HEAD` request with an `If-Match` header, the
61+
service **must** proceed with the request if the ETag matches, or send a
62+
`412 Precondition Failed` error if the ETag does not match.
63+
64+
If a service receives a `GET` or `HEAD` request with an `If-None-Match` header,
65+
the service **must** proceed with the request if the ETag does not match, or
66+
return a `304 Not Modified` response if the ETag does match.
67+
68+
### Strong and weak ETags
69+
70+
ETags can be either "strongly validated" or "weakly validated":
71+
72+
- A strongly validated ETag means that two resources bearing the same ETag are
73+
byte-for-byte identical.
74+
- A weakly validated ETag means that two resources bearing the same ETag are
75+
equivalent, but may differ in ways that the service does not consider to be
76+
important.
77+
78+
Resources **may** use either strong or weak ETags, as it sees fit, but
79+
**should** document the behavior. Additionally, weak ETags **must** have a `W/`
80+
prefix as mandated by [RFC 7232][]:
81+
82+
```
83+
200 OK
84+
Content-type: application/json
85+
ETag: W/"55cc0347-66fc-46c3-a26f-98a9a7d61d0e"
86+
```
87+
88+
Strong ETags **must** and weak ETags **should** be guaranteed to change if any
89+
properties on the resource change that are directly mutable by the client.
90+
Additionally, strong ETags **should** be guaranteed to change if the resource's
91+
representation changes in a meaningful way (meaning the new representation is
92+
not equivalent to the old one).
93+
94+
## Further reading
95+
96+
- For how to retry on errors in client libraries, see AIP-194.
97+
98+
## Changelog
99+
100+
- **2020-09-02**: Clarified that other errors may take precedence over
101+
`FAILED_PRECONDITION` for ETag mismatches.
102+
- **2020-09-02**: Add guidance for ETags on request messages.
103+
- **2019-09-23**: Changed the title to "resource freshness validation".
104+
105+
[rfc 7232]: https://tools.ietf.org/html/rfc7232#section-2.3

aip/general/0154/aip.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
id: 154
3+
state: approved
4+
created: 2019-07-24
5+
placement:
6+
category: design-patterns
7+
order: 30

0 commit comments

Comments
 (0)