|
| 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 |
0 commit comments