Network Working Group | J. Jena |
Internet-Draft | S. Dalal |
Intended status: Standards Track | November 16, 2023 |
Expires: May 19, 2024 |
The HTTP Idempotency-Key request header field can be used to carry idempotency key in order to make non-idempotent HTTP methods such as POST or PATCH fault-tolerant.¶
This note is to be removed before publishing as an RFC.¶
Status information for this document may be found at <https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/>.¶
Discussion of this document takes place on the HTTPAPI Working Group mailing list (<mailto:httpapi@ietf.org>), which is archived at <https://mailarchive.ietf.org/arch/browse/httpapi/>. Subscribe at <https://www.ietf.org/mailman/listinfo/httpapi/>. Working Group information can be found at <https://ietf-wg-httpapi.github.io/>.¶
Source for this draft and an issue tracker can be found at <https://github.com/ietf-wg-httpapi/idempotency>.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as “work in progress”.¶
This Internet-Draft will expire on May 19, 2024.¶
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application. It does not matter if the operation is called only once, or 10s of times over.¶
Idempotency is important in building a fault-tolerant HTTP API. An HTTP request method is considered idempotent if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. According to [RFC7231], HTTP methods OPTIONS, HEAD, GET, PUT and DELETE are idempotent while methods POST and PATCH are not.¶
Let's say a client of an HTTP API wants to create (or update) a resource using a POST method. Since POST is NOT an idempotent method, calling it multiple times can result in duplication or wrong updates. Consider a scenario where the client sent a POST request to the server, but it got a timeout. Following questions arise : Is the resource actually created (or updated)? Did the timeout occur during sending of the request, or when receiving of the response? Can the client safely retry the request, or does it need to figure out what happened in the first place? If POST had been an idempotent method, such questions may not arise. Client would safely retry a request until it actually gets a valid response from the server.¶
For many use cases of HTTP APIs, duplicated resources are a severe problem from a business perspective. For example, duplicate records for requests involving any kind of money transfer MUST NOT be allowed. In other cases, processing of duplicate webhook delivery is not expected.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
This specification uses the Augmented Backus-Naur Form (ABNF) notation of [RFC5234] and includes, by reference, the IMF-fixdate rule as defined in Section 7.1.1.1 of [RFC7231].¶
An idempotency key is a unique value generated by the client which the resource server uses to recognize subsequent retries of the same request. The Idempotency-Key HTTP request header field carries this key.¶
Idempotency-Key is an Item Structured Header [RFC8941]. Its value MUST be a String. Refer to Section 3.3.3 of [RFC8941] for ABNF of sf-string:¶
Idempotency-Key = sf-string
Clients MUST NOT include more than one Idempotency-Key header field in the same request.¶
Idempotency-Key: "8e03978e-40d5-43e8-bc93-6894a57f9324"
The idempotency key that is supplied as part of every POST request MUST be unique and MUST NOT be reused with another request with a different request payload.¶
The resource MAY enforce time based idempotency keys, thus, be able to purge or delete a key upon its expiry. The resource server SHOULD define such expiration policy and publish it in the documentation.¶
An idempotency fingerprint MAY be used in conjunction with an idempotency key to determine the uniqueness of a request. Such a fingerprint is generated from request payload data by the resource server. An idempotency fingerprint generation algorithm MAY use one of the following or similar approaches to create a fingerprint.¶
Client¶
Clients of HTTP API requiring idempotency, SHOULD understand the idempotency related requirements as published by the server and use appropriate algorithm to generate idempotency keys.¶
Clients MAY choose to send an Idempotency-Key field with any valid random sf-string to indicate the user's intent is to only perform this action once. Without a priori knowledge, a general client cannot assume the server will respect this request.¶
For each request, client SHOULD ¶
Resource Server¶
Resource server MUST publish idempotency related specification. This specification MUST include expiration related policy if applicable. Server is responsible for managing the lifecycle of the idempotency key.¶
For each request, server SHOULD ¶
If the Idempotency-Key request header is missing for a documented idempotent operation requiring this header, the resource server SHOULD reply with an HTTP 400 status code with body containing a link pointing to relevant documentation. Following examples shows an error response describing the problem using [RFC7807].¶
HTTP/1.1 400 Bad Request Content-Type: application/problem+json Content-Language: en { "type": "https://developer.example.com/idempotency", "title": "Idempotency-Key is missing", "detail": "This operation is idempotent and it requires correct usage of Idempotency Key.", }
Alternately, using the HTTP header Link, the client can be informed about the error as shown below.¶
HTTP/1.1 400 Bad Request Link: <https://developer.example.com/idempotency>; rel="describedby"; type="text/html"
If there is an attempt to reuse an idempotency key with a different request payload, the resource server SHOULD reply with a HTTP 422 status code with body containing a link pointing to relevant documentation. The status code 422 is defined in Section 11.2 of [RFC4918].¶
HTTP/1.1 422 Unprocessable Content Content-Type: application/problem+json Content-Language: en { "type": "https://developer.example.com/idempotency", "title": "Idempotency-Key is already used", "detail": "This operation is idempotent and it requires correct usage of Idempotency Key. Idempotency Key MUST not be reused across different payloads of this operation.", }
The server can also inform the client by using the HTTP header Link as shown below.¶
HTTP/1.1 422 Unprocessable Content Link: <https://developer.example.com/idempotency>; rel="describedby"; type="text/html"
If the request is retried, while the original request is still being processed, the resource server SHOULD reply with an HTTP 409 status code with body containing problem description.¶
HTTP/1.1 409 Conflict Content-Type: application/problem+json Content-Language: en { "type": "https://developer.example.com/idempotency", "title": "A request is outstanding for this Idempotency-Key", "detail": "A request with the same Idempotency-Key for the same operation is being processed or is outstanding.", }
Or, alternately using the HTTP header Link pointing to the relevant documentation¶
HTTP/1.1 409 Conflict Link: <https://developer.example.com/idempotency>; rel="describedby"; type="text/html"
Error scenarios above describe the status of failed idempotent requests after the resource server prcocesses them. Clients MUST correct the requests (with the exception of 409 where no correction is required) before performing a retry operation, or the the resource server MUST fail the request and return one of the above errors.¶
For other 4xx/5xx errors, such as 401, 403, 500, 502, 503, 504, 429, or any other HTTP error code that is not listed here, the client SHOULD act appropriately by following the resource server's documentation.¶
The Idempotency-Key field name should be added to the "Hypertext Transfer Protocol (HTTP) Field Name Registry".¶
Note to RFC Editor: Please remove this section before publication.¶
This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in [RFC7942]. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist.¶
According to RFC 7942, "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit".¶
Organization: Stripe¶
Organization: Adyen¶
Organization: Dwolla¶
Organization: Interledger¶
Organization: WorldPay¶
Organization: Yandex¶
Organization: http4s.org¶
Organization: Finastra¶
Organization: Datatrans¶
This is a list of implementations that implement the general concept, but do so using different mechanisms:¶
Organization: Django¶
Organization: Twilio¶
Organization: PayPal¶
Organization: RazorPay¶
Organization: OpenBanking¶
Organization: Square¶
Organization: Google Standard Payments¶
Organization: BBVA¶
Organization: WebEngage¶
This section is meant to inform developers, information providers, and users of known security concerns specific to the idempotency keys.¶
Resource servers that do not implement strong idempotency keys, such as UUIDs, or have appropriate controls to validate the idempotency keys, could be victim to various forms of security attacks from malicious clients:¶
To prevent such situations, the specification recommends the following best practices for idempotency key implementation in the resource server.¶
The first example shows an idempotency-key header field with key value using UUID version 4 scheme:¶
Idempotency-Key: "8e03978e-40d5-43e8-bc93-6894a57f9324"
Second example shows an idempotency-key header field with key value using some random string generator:¶
Idempotency-Key: "clkyoesmbgybucifusbbtdsbohtyuuwz"
The following core rules are included by reference, as defined in Appendix B.1 of [RFC5234]: ALPHA (letters), CR (carriage return), CRLF (CR LF), CTL (controls), DIGIT (decimal 0-9), DQUOTE (double quote), HEXDIG (hexadecimal 0-9/A-F/a-f), LF (line feed), OCTET (any 8-bit sequence of data), SP (space), and VCHAR (any visible US-ASCII character).¶
obs-text = <obs-text, see [RFC7230], Section 3.2.6>
The authors would like to thank Mark Nottingham for his support for this Internet Draft. We would like to acknowledge that this draft is inspired by Idempotency related patterns described in API documentation of PayPal and Stripe as well as Internet Draft on POST Once Exactly authored by Mark Nottingham.¶
The authors take all responsibility for errors and omissions.¶