From adf77ee358a0b4be4f9ca6b57c5e9dd2b1b0a7e9 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Sat, 18 Jan 2025 12:27:00 -0800 Subject: [PATCH 1/2] feat(AEP-154): update to conform to RFC 9110, clarify precondition error code RFC 9110 obsoletes RFC 7232 and clarifies some details. In addition, clarifying expectation of behavior on preconditions which are not supported. They should be rejected to help indicate the lack of support to the user. Fixes #254. --- aep/general/0154/aep.md.j2 | 44 ++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/aep/general/0154/aep.md.j2 b/aep/general/0154/aep.md.j2 index 8b615a50..f3301a56 100644 --- a/aep/general/0154/aep.md.j2 +++ b/aep/general/0154/aep.md.j2 @@ -23,11 +23,11 @@ ETag: "55cc0347-66fc-46c3-a26f-98a9a7d61d0e" ``` The ETag **must** be provided by the server on output, and values **should** -conform to [RFC 7232][]. Resources **must** support the `If-Match` header (and +conform to [RFC 9110][]. Resources **must** support the `If-Match` header (and **may** support the `If-None-Match` header) if and only if resources provide the ETag. -**Note:** ETag values **must** include quotes as described in [RFC 7232][]. For +**Note:** ETag values **must** include quotes as described in [RFC 9110][]. For example, a valid ETag is `"foo"`, not `foo`. ETags **must** be based on an opaque checksum or hash of the resource that @@ -35,8 +35,16 @@ guarantees it will change if the resource changes. ### Condition headers -Services that provide ETags **should** support the `If-Match` and -`If-None-Match` headers on incoming requests: +Services that provide ETags **should** support all applicable +[preconditions](https://www.rfc-editor.org/rfc/rfc9110.html#name-preconditions) +documented in RFC 9110, including: + +- `If-match` +- `If-None-Match` +- `If-Modified-Since` +- `If-Unmodified-Since` + +An example of using `If-match`: ```http GET /v1/publishers/{publisher}/books/{book} HTTP/2 @@ -60,10 +68,14 @@ the same conditional headers **must** be supported for all mutation methods (`POST`, `PATCH`, `PUT`, and `DELETE`) of any path that supports them, and **should** be supported uniformly for all operations across the service. +If a server recieves a conditional header it does not support, the service +**should** return an `INAVLID_ARGUMENT / 400` response. + If any validator or conditional headers are supported for any operations in the -service, the use of unsupported conditional headers **must** result in an -error. (In other words, once a service gives the client reason to believe it -understands conditional headers, it **must not** ever ignore them.) +service, the use of unsupported conditional headers **must** result in a +`INVALID_ARGUMENT / 400` error response. (In other words, once a service gives +the client reason to believe it understands conditional headers, it **must not** +ever ignore them.) ### Read requests @@ -87,7 +99,7 @@ ETags can be either "strongly validated" or "weakly validated": Resources **may** use either strong or weak ETags, as it sees fit, but **should** document the behavior. Additionally, weak ETags **must** have a `W/` -prefix as mandated by [RFC 7232][]: +prefix as mandated by [RFC 9110 Etag Comparison][]: ``` 200 OK @@ -95,22 +107,26 @@ Content-type: application/json ETag: W/"55cc0347-66fc-46c3-a26f-98a9a7d61d0e" ``` +**NOTE**: The strong match **must** be used when comparing +[`If-match`](https://www.rfc-editor.org/rfc/rfc9110.html#name-if-match), while +the weak match **must** be used when evaluating the +[`If-None-Match`](https://www.rfc-editor.org/rfc/rfc9110.html#name-if-none-match) +as stated in RFC-9110. + Strong ETags **must** and weak ETags **should** be guaranteed to change if any properties on the resource change that are directly mutable by the client. Additionally, strong ETags **should** be guaranteed to change if the resource's representation changes in a meaningful way (meaning the new representation is not equivalent to the old one). -## Further reading - -- For how to retry on errors in client libraries, see AEP-194. - ## Changelog +- **2025-01-18**: Updated to use RFC 9110 instead of RFC 7232, which is deprecated. - **2020-09-02**: Clarified that other errors may take precedence over `FAILED_PRECONDITION` for ETag mismatches. - **2020-09-02**: Add guidance for ETags on request messages. - **2019-09-23**: Changed the title to "resource freshness validation". -[rfc 7232]: https://tools.ietf.org/html/rfc7232#section-2.3 -[strong consistency]: ./0121.md#strong-consistency +[RFC 9110]: https://www.rfc-editor.org/rfc/rfc9110.html#section-8.8.3 +[RFC 9110 Etags Comparison]: https://www.rfc-editor.org/rfc/rfc9110.html#name-comparison-2 +[strong consistency]: ./0121.md#strong-consistency \ No newline at end of file From dc3aae73227e01c6619811c61d4d822a0b34b222 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 21 Jan 2025 15:46:41 -0800 Subject: [PATCH 2/2] address feedback. --- aep/general/0154/aep.md.j2 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/aep/general/0154/aep.md.j2 b/aep/general/0154/aep.md.j2 index f3301a56..bfbfdcce 100644 --- a/aep/general/0154/aep.md.j2 +++ b/aep/general/0154/aep.md.j2 @@ -35,16 +35,17 @@ guarantees it will change if the resource changes. ### Condition headers -Services that provide ETags **should** support all applicable +When adding precondition checking to an API, the headers and behaviors **must** +match [preconditions](https://www.rfc-editor.org/rfc/rfc9110.html#name-preconditions) -documented in RFC 9110, including: +as documented in RFC 9110. -- `If-match` -- `If-None-Match` -- `If-Modified-Since` -- `If-Unmodified-Since` +### If-Match / If-None-Match -An example of using `If-match`: +Services that provide ETags **should** support the `If-Match` and +`If-None-Match` headers. + +An example of using `If-Match`: ```http GET /v1/publishers/{publisher}/books/{book} HTTP/2