draft-ietf-httpapi-ratelimit-headers-00.unpg.txt   draft-ietf-httpapi-ratelimit-headers-latest.txt 
HTTPAPI Working Group R. Polli HTTPAPI Working Group R. Polli
Internet-Draft Team Digitale, Italian Government Internet-Draft Team Digitale, Italian Government
Intended status: Standards Track A. Martinez Intended status: Standards Track A. Martinez
Expires: June 21, 2021 Red Hat Expires: July 18, 2021 Red Hat
December 18, 2020 January 14, 2021
RateLimit Header Fields for HTTP RateLimit Header Fields for HTTP
draft-ietf-httpapi-ratelimit-headers-00 draft-ietf-httpapi-ratelimit-headers-latest
Abstract Abstract
This document defines the RateLimit-Limit, RateLimit-Remaining, This document defines the RateLimit-Limit, RateLimit-Remaining,
RateLimit-Reset fields for HTTP, thus allowing servers to publish RateLimit-Reset fields for HTTP, thus allowing servers to publish
current request quotas and clients to shape their request policy and current request quotas and clients to shape their request policy and
avoid being throttled out. avoid being throttled out.
Note to Readers Note to Readers
skipping to change at line 44 skipping to change at page 1, line 45
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on June 21, 2021. This Internet-Draft will expire on July 18, 2021.
Copyright Notice Copyright Notice
Copyright (c) 2020 IETF Trust and the persons identified as the Copyright (c) 2021 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of (https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License. described in the Simplified BSD License.
Table of Contents Table of Contents
1. Introduction 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Rate-limiting and quotas 1.1. Rate-limiting and quotas . . . . . . . . . . . . . . . . 3
1.2. Current landscape of rate-limiting headers 1.2. Current landscape of rate-limiting headers . . . . . . . 4
1.2.1. Interoperability issues 1.2.1. Interoperability issues . . . . . . . . . . . . . . . 4
1.3. This proposal 1.3. This proposal . . . . . . . . . . . . . . . . . . . . . . 5
1.4. Goals 1.4. Goals . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5. Notational Conventions 1.5. Notational Conventions . . . . . . . . . . . . . . . . . 6
2. Expressing rate-limit policies 2. Expressing rate-limit policies . . . . . . . . . . . . . . . 6
2.1. Time window 2.1. Time window . . . . . . . . . . . . . . . . . . . . . . . 6
2.2. Request quota 2.2. Request quota . . . . . . . . . . . . . . . . . . . . . . 6
2.3. Quota policy 2.3. Quota policy . . . . . . . . . . . . . . . . . . . . . . 7
3. Header Specifications 3. Header Specifications . . . . . . . . . . . . . . . . . . . . 8
3.1. RateLimit-Limit 3.1. RateLimit-Limit . . . . . . . . . . . . . . . . . . . . . 8
3.2. RateLimit-Remaining 3.2. RateLimit-Remaining . . . . . . . . . . . . . . . . . . . 9
3.3. RateLimit-Reset 3.3. RateLimit-Reset . . . . . . . . . . . . . . . . . . . . . 9
4. Providing RateLimit headers 4. Providing RateLimit headers . . . . . . . . . . . . . . . . . 10
5. Intermediaries 5. Intermediaries . . . . . . . . . . . . . . . . . . . . . . . 11
6. Caching 6. Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
7. Receiving RateLimit headers 7. Receiving RateLimit headers . . . . . . . . . . . . . . . . . 11
8. Examples 8. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 12
8.1. Unparameterized responses 8.1. Unparameterized responses . . . . . . . . . . . . . . . . 12
8.1.1. Throttling informations in responses 8.1.1. Throttling informations in responses . . . . . . . . 12
8.1.2. Use in conjunction with custom headers 8.1.2. Use in conjunction with custom headers . . . . . . . 13
8.1.3. Use for limiting concurrency 8.1.3. Use for limiting concurrency . . . . . . . . . . . . 13
8.1.4. Use in throttled responses 8.1.4. Use in throttled responses . . . . . . . . . . . . . 14
8.2. Parameterized responses 8.2. Parameterized responses . . . . . . . . . . . . . . . . . 15
8.2.1. Throttling window specified via parameter 8.2.1. Throttling window specified via parameter . . . . . . 15
8.2.2. Dynamic limits with parameterized windows 8.2.2. Dynamic limits with parameterized windows . . . . . . 16
8.2.3. Dynamic limits for pushing back and slowing down 8.2.3. Dynamic limits for pushing back and slowing down . . 16
8.3. Dynamic limits for pushing back with Retry-After and slow 8.3. Dynamic limits for pushing back with Retry-After and slow
down down . . . . . . . . . . . . . . . . . . . . . . . . . . 17
8.3.1. Missing Remaining informations
8.3.2. Use with multiple windows 8.3.1. Missing Remaining informations . . . . . . . . . . . 18
9. Security Considerations 8.3.2. Use with multiple windows . . . . . . . . . . . . . . 19
9.1. Throttling does not prevent clients from issuing requests 9. Security Considerations . . . . . . . . . . . . . . . . . . . 19
9.2. Information disclosure 9.1. Throttling does not prevent clients from issuing requests 19
9.3. Remaining quota-units are not granted requests 9.2. Information disclosure . . . . . . . . . . . . . . . . . 20
9.4. Reliability of RateLimit-Reset 9.3. Remaining quota-units are not granted requests . . . . . 20
9.5. Resource exhaustion 9.4. Reliability of RateLimit-Reset . . . . . . . . . . . . . 20
9.6. Denial of Service 9.5. Resource exhaustion . . . . . . . . . . . . . . . . . . . 20
10. IANA Considerations 9.6. Denial of Service . . . . . . . . . . . . . . . . . . . . 21
10.1. RateLimit-Limit Field Registration 10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 21
10.2. RateLimit-Remaining Field Registration 10.1. RateLimit-Limit Field Registration . . . . . . . . . . . 21
10.3. RateLimit-Reset Field Registration 10.2. RateLimit-Remaining Field Registration . . . . . . . . . 21
11. References 10.3. RateLimit-Reset Field Registration . . . . . . . . . . . 22
11.1. Normative References 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 22
11.2. Informative References 11.1. Normative References . . . . . . . . . . . . . . . . . . 22
11.3. URIs 11.2. Informative References . . . . . . . . . . . . . . . . . 23
Appendix A. Change Log 11.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Appendix B. Acknowledgements Appendix A. Change Log . . . . . . . . . . . . . . . . . . . . . 23
Appendix C. RateLimit headers currently used on the web Appendix B. Acknowledgements . . . . . . . . . . . . . . . . . . 23
Appendix D. FAQ Appendix C. RateLimit headers currently used on the web . . . . 24
Authors' Addresses Appendix D. FAQ . . . . . . . . . . . . . . . . . . . . . . . . 25
Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
E.1. Since draft-ietf-httpapi-ratelimit-headers-00 . . . . . . 28
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 28
1. Introduction 1. Introduction
The widespreading of HTTP as a distributed computation protocol The widespreading of HTTP as a distributed computation protocol
requires an explicit way of communicating service status and usage requires an explicit way of communicating service status and usage
quotas. quotas.
This was partially addressed with the "Retry-After" header field This was partially addressed with the "Retry-After" header field
defined in [SEMANTICS] to be returned in "429 Too Many Requests" or defined in [SEMANTICS] to be returned in "429 Too Many Requests" or
"503 Service Unavailable" responses. "503 Service Unavailable" responses.
skipping to change at line 207 skipping to change at page 5, line 23
o "RateLimit-Limit": containing the requests quota in the time o "RateLimit-Limit": containing the requests quota in the time
window; window;
o "RateLimit-Remaining": containing the remaining requests quota in o "RateLimit-Remaining": containing the remaining requests quota in
the current window; the current window;
o "RateLimit-Reset": containing the time remaining in the current o "RateLimit-Reset": containing the time remaining in the current
window, specified in seconds. window, specified in seconds.
The behavior of "RateLimit-Reset" is compatible with the "delta- The behavior of "RateLimit-Reset" is compatible with the "delay-
seconds" notation of "Retry-After". seconds" notation of "Retry-After".
The fields definition allows to describe complex policies, including The fields definition allows to describe complex policies, including
the ones using multiple and variable time windows and dynamic quotas, the ones using multiple and variable time windows and dynamic quotas,
or implementing concurrency limits. or implementing concurrency limits.
1.4. Goals 1.4. Goals
The goals of this proposal are: The goals of this proposal are:
skipping to change at line 233 skipping to change at page 5, line 49
3. Simplify API documentation avoiding expliciting rate-limit fields 3. Simplify API documentation avoiding expliciting rate-limit fields
semantic in documentation. semantic in documentation.
The goals do not include: The goals do not include:
Authorization: The rate-limit headers described here are not meant Authorization: The rate-limit headers described here are not meant
to support authorization or other kinds of access controls. to support authorization or other kinds of access controls.
Throttling scope: This specification does not cover the throttling Throttling scope: This specification does not cover the throttling
scope, that may be the given resource-target, its parent path or scope, that may be the given resource-target, its parent path or
the whole Origin [RFC6454] section 7. the whole Origin (see Section 7 of [RFC6454]).
Response status code: The rate-limit headers may be returned in both Response status code: The rate-limit headers may be returned in both
Successful and non Successful responses. This specification does Successful and non Successful responses. This specification does
not cover whether non Successful responses count on quota usage. not cover whether non Successful responses count on quota usage.
Throttling policy: This specification does not mandate a specific Throttling policy: This specification does not mandate a specific
throttling policy. The values published in the headers, including throttling policy. The values published in the headers, including
the window size, can be statically or dynamically evaluated. the window size, can be statically or dynamically evaluated.
Service Level Agreement: Conveyed quota hints do not imply any Service Level Agreement: Conveyed quota hints do not imply any
skipping to change at line 256 skipping to change at page 6, line 26
1.5. Notational Conventions 1.5. Notational Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in "OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here. capitals, as shown here.
This document uses the Augmented BNF defined in [RFC5234] and updated This document uses the Augmented BNF defined in [RFC5234] and updated
by [RFC7405] along with the "#rule" extension defined in Section 7 of by [RFC7405] along with the "#rule" extension defined in
[MESSAGING]. Section 5.6.1 of [SEMANTICS].
The term Origin is to be interpreted as described in [RFC6454] The term Origin is to be interpreted as described in Section 7 of
section 7. [RFC6454].
The "delta-seconds" rule is defined in [CACHING] section 1.2.1. The "delay-seconds" rule is defined in Section 10.2.4 of [SEMANTICS].
2. Expressing rate-limit policies 2. Expressing rate-limit policies
2.1. Time window 2.1. Time window
Rate limit policies limit the number of acceptable requests in a Rate limit policies limit the number of acceptable requests in a
given time window. given time window.
A time window is expressed in seconds, using the following syntax: A time window is expressed in seconds, using the following syntax:
time-window = delta-seconds time-window = delay-seconds
Subsecond precision is not supported. Subsecond precision is not supported.
2.2. Request quota 2.2. Request quota
The request-quota is a value associated to the maximum number of The request-quota is a value associated to the maximum number of
requests that the server is willing to accept from one or more requests that the server is willing to accept from one or more
clients on a given basis (originating IP, authenticated user, clients on a given basis (originating IP, authenticated user,
geographical, ..) during a "time-window" as defined in Section 2.1. geographical, ..) during a "time-window" as defined in Section 2.1.
skipping to change at line 412 skipping to change at page 9, line 38
RateLimit-Remaining: 50 RateLimit-Remaining: 50
3.3. RateLimit-Reset 3.3. RateLimit-Reset
The "RateLimit-Reset" response field indicates either The "RateLimit-Reset" response field indicates either
o the number of seconds until the quota resets. o the number of seconds until the quota resets.
The header value is The header value is
RateLimit-Reset = delta-seconds RateLimit-Reset = delay-seconds
The delta-seconds format is used because: The delay-seconds format is used because:
o it does not rely on clock synchronization and is resilient to o it does not rely on clock synchronization and is resilient to
clock adjustment and clock skew between client and server (see clock adjustment and clock skew between client and server (see
[SEMANTICS] Section 4.1.1.1); Section 5.6.7 of [SEMANTICS]);
o it mitigates the risk related to thundering herd when too many o it mitigates the risk related to thundering herd when too many
clients are serviced with the same timestamp. clients are serviced with the same timestamp.
This header MUST NOT occur multiple times and can be sent in a This header MUST NOT occur multiple times and can be sent in a
trailer section. trailer section.
An example of "RateLimit-Reset" use is below. An example of "RateLimit-Reset" use is below.
RateLimit-Reset: 50 RateLimit-Reset: 50
skipping to change at line 477 skipping to change at page 11, line 7
field values between subsequent requests, eg. to respond to Denial of field values between subsequent requests, eg. to respond to Denial of
Service attacks or in case of resource saturation. Service attacks or in case of resource saturation.
Servers usually establish whether the request is in-quota before Servers usually establish whether the request is in-quota before
creating a response, so the RateLimit field values should be already creating a response, so the RateLimit field values should be already
available in that moment. Nonetheless servers MAY decide to send the available in that moment. Nonetheless servers MAY decide to send the
"RateLimit" fields in a trailer section. "RateLimit" fields in a trailer section.
5. Intermediaries 5. Intermediaries
This section documents the considerations advised in Section 15.3.3 This section documents the considerations advised in Section 16.3.3
of [SEMANTICS]. of [SEMANTICS].
An intermediary that is not part of the originating service An intermediary that is not part of the originating service
infrastructure and is not aware of the quota-policy semantic used by infrastructure and is not aware of the quota-policy semantic used by
the Origin Server SHOULD NOT alter the RateLimit fields' values in the Origin Server SHOULD NOT alter the RateLimit fields' values in
such a way as to communicate a more permissive quota-policy; this such a way as to communicate a more permissive quota-policy; this
includes removing the RateLimit fields. includes removing the RateLimit fields.
An intermediary MAY alter the RateLimit fields in such a way as to An intermediary MAY alter the RateLimit fields in such a way as to
communicate a more restrictive quota-policy when: communicate a more restrictive quota-policy when:
skipping to change at line 556 skipping to change at page 12, line 38
8.1. Unparameterized responses 8.1. Unparameterized responses
8.1.1. Throttling informations in responses 8.1.1. Throttling informations in responses
The client exhausted its request-quota for the next 50 seconds. The The client exhausted its request-quota for the next 50 seconds. The
"time-window" is communicated out-of-band or inferred by the header "time-window" is communicated out-of-band or inferred by the header
values. values.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 100 RateLimit-Limit: 100
Ratelimit-Remaining: 0 Ratelimit-Remaining: 0
Ratelimit-Reset: 50 Ratelimit-Reset: 50
{"hello": "world"} {"hello": "world"}
skipping to change at line 591 skipping to change at page 13, line 28
The server then exposes the "RateLimit-*" headers to inform the The server then exposes the "RateLimit-*" headers to inform the
client that: client that:
o it has only 100 quota-units left; o it has only 100 quota-units left;
o the window will reset in 10 hours. o the window will reset in 10 hours.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
acme-RateLimit-DayLimit: 5000 acme-RateLimit-DayLimit: 5000
acme-RateLimit-HourLimit: 1000 acme-RateLimit-HourLimit: 1000
RateLimit-Limit: 5000 RateLimit-Limit: 5000
RateLimit-Remaining: 100 RateLimit-Remaining: 100
RateLimit-Reset: 36000 RateLimit-Reset: 36000
skipping to change at line 619 skipping to change at page 14, line 9
increasing availability. increasing availability.
The server adopted a basic policy of 100 quota-units per minute, and The server adopted a basic policy of 100 quota-units per minute, and
in case of resource exhaustion adapts the returned values reducing in case of resource exhaustion adapts the returned values reducing
both "RateLimit-Limit" and "RateLimit-Remaining". both "RateLimit-Limit" and "RateLimit-Remaining".
After 2 seconds the client consumed 40 quota-units After 2 seconds the client consumed 40 quota-units
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 100 RateLimit-Limit: 100
RateLimit-Remaining: 60 RateLimit-Remaining: 60
RateLimit-Reset: 58 RateLimit-Reset: 58
{"elapsed": 2, "issued": 40} {"elapsed": 2, "issued": 40}
At the subsequent request - due to resource exhaustion - the server At the subsequent request - due to resource exhaustion - the server
advertises only "RateLimit-Remaining: 20". advertises only "RateLimit-Remaining: 20".
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 100 RateLimit-Limit: 100
RateLimit-Remaining: 20 RateLimit-Remaining: 20
RateLimit-Reset: 56 RateLimit-Reset: 56
{"elapsed": 4, "issued": 41} {"elapsed": 4, "issued": 41}
skipping to change at line 661 skipping to change at page 15, line 7
sending the "Retry-After" response header field. sending the "Retry-After" response header field.
In this example, the values of "Retry-After" and "RateLimit-Reset" In this example, the values of "Retry-After" and "RateLimit-Reset"
reference the same moment, but this is not a requirement. reference the same moment, but this is not a requirement.
The "429 Too Many Requests" HTTP status code is just used as an The "429 Too Many Requests" HTTP status code is just used as an
example. example.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 429 Too Many Requests HTTP/1.1 429 Too Many Requests
Content-Type: application/json Content-Type: application/json
Date: Mon, 05 Aug 2019 09:27:00 GMT Date: Mon, 05 Aug 2019 09:27:00 GMT
Retry-After: Mon, 05 Aug 2019 09:27:05 GMT Retry-After: Mon, 05 Aug 2019 09:27:05 GMT
RateLimit-Reset: 5 RateLimit-Reset: 5
RateLimit-Limit: 100 RateLimit-Limit: 100
Ratelimit-Remaining: 0 Ratelimit-Remaining: 0
skipping to change at line 689 skipping to change at page 15, line 36
8.2. Parameterized responses 8.2. Parameterized responses
8.2.1. Throttling window specified via parameter 8.2.1. Throttling window specified via parameter
The client has 99 "quota-units" left for the next 50 seconds. The The client has 99 "quota-units" left for the next 50 seconds. The
"time-window" is communicated by the "w" parameter, so we know the "time-window" is communicated by the "w" parameter, so we know the
throughput is 100 "quota-units" per minute. throughput is 100 "quota-units" per minute.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 100, 100;w=60 RateLimit-Limit: 100, 100;w=60
Ratelimit-Remaining: 99 Ratelimit-Remaining: 99
Ratelimit-Reset: 50 Ratelimit-Reset: 50
{"hello": "world"} {"hello": "world"}
skipping to change at line 718 skipping to change at page 16, line 22
The "RateLimit-Remaining" then advertises only 9 quota-units for the The "RateLimit-Remaining" then advertises only 9 quota-units for the
next 50 seconds to slow down the client. next 50 seconds to slow down the client.
Note that the server could have lowered even the other values in Note that the server could have lowered even the other values in
"RateLimit-Limit": this specification does not mandate any relation "RateLimit-Limit": this specification does not mandate any relation
between the field values contained in subsequent responses. between the field values contained in subsequent responses.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 10, 100;w=60 RateLimit-Limit: 10, 100;w=60
Ratelimit-Remaining: 9 Ratelimit-Remaining: 9
Ratelimit-Reset: 50 Ratelimit-Reset: 50
{ {
skipping to change at line 746 skipping to change at page 17, line 5
seconds and performs a new request which, due to resource exhaustion, seconds and performs a new request which, due to resource exhaustion,
the server rejects and pushes back, advertising "RateLimit-Remaining: the server rejects and pushes back, advertising "RateLimit-Remaining:
0" for the next 20 seconds. 0" for the next 20 seconds.
The server advertises a smaller window with a lower limit to slow The server advertises a smaller window with a lower limit to slow
down the client for the rest of its original window after the 20 down the client for the rest of its original window after the 20
seconds elapse. seconds elapse.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 429 Too Many Requests HTTP/1.1 429 Too Many Requests
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 0, 15;w=20 RateLimit-Limit: 0, 15;w=20
Ratelimit-Remaining: 0 Ratelimit-Remaining: 0
Ratelimit-Reset: 20 Ratelimit-Reset: 20
{ {
skipping to change at line 774 skipping to change at page 17, line 34
starts, we can convey the same information to the client via the starts, we can convey the same information to the client via the
Retry-After header, with the advantage that the server can now Retry-After header, with the advantage that the server can now
specify the policy's nominal limit and window that will apply after specify the policy's nominal limit and window that will apply after
the reset, ie. assuming the resource exhaustion is likely to be gone the reset, ie. assuming the resource exhaustion is likely to be gone
by then, so the advertised policy does not need to be adjusted, yet by then, so the advertised policy does not need to be adjusted, yet
we managed to stop requests for a while and slow down the rest of the we managed to stop requests for a while and slow down the rest of the
current window. current window.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 429 Too Many Requests HTTP/1.1 429 Too Many Requests
Content-Type: application/json Content-Type: application/json
Retry-After: 20 Retry-After: 20
RateLimit-Limit: 15, 100;w=60 RateLimit-Limit: 15, 100;w=60
Ratelimit-Remaining: 15 Ratelimit-Remaining: 15
Ratelimit-Reset: 40 Ratelimit-Reset: 40
skipping to change at line 789 skipping to change at page 18, line 4
Content-Type: application/json Content-Type: application/json
Retry-After: 20 Retry-After: 20
RateLimit-Limit: 15, 100;w=60 RateLimit-Limit: 15, 100;w=60
Ratelimit-Remaining: 15 Ratelimit-Remaining: 15
Ratelimit-Reset: 40 Ratelimit-Reset: 40
{ {
"status": 429, "status": 429,
"detail": "Wait 20 seconds, then slow down!" "detail": "Wait 20 seconds, then slow down!"
} }
Note that in this last response the client is expected to honor the Note that in this last response the client is expected to honor the
"Retry-After" header and perform no requests for the specified amount "Retry-After" header and perform no requests for the specified amount
of time, whereas the previous example would not force the client to of time, whereas the previous example would not force the client to
stop requests before the reset time is elapsed, as it would still be stop requests before the reset time is elapsed, as it would still be
free to query again the server even if it is likely to have the free to query again the server even if it is likely to have the
request rejected. request rejected.
8.3.1. Missing Remaining informations 8.3.1. Missing Remaining informations
The server does not expose "RateLimit-Remaining" values, but resets The server does not expose "RateLimit-Remaining" values, but resets
the limit counter every second. the limit counter every second.
It communicates to the client the limit of 10 quota-units per second It communicates to the client the limit of 10 quota-units per second
always returning the couple "RateLimit-Limit" and "RateLimit-Reset". always returning the couple "RateLimit-Limit" and "RateLimit-Reset".
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 10 RateLimit-Limit: 10
Ratelimit-Reset: 1 Ratelimit-Reset: 1
{"first": "request"} {"first": "request"}
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 Ok HTTP/1.1 200 Ok
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 10 RateLimit-Limit: 10
Ratelimit-Reset: 1 Ratelimit-Reset: 1
{"second": "request"} {"second": "request"}
skipping to change at line 856 skipping to change at page 19, line 30
that: that:
o it has only 100 quota-units left; o it has only 100 quota-units left;
o the window will reset in 10 hours; o the window will reset in 10 hours;
o the "expiring-limit" is 5000. o the "expiring-limit" is 5000.
Request: Request:
GET /items/123 GET /items/123 HTTP/1.1
Host: api.example
Response: Response:
HTTP/1.1 200 OK HTTP/1.1 200 OK
Content-Type: application/json Content-Type: application/json
RateLimit-Limit: 5000, 1000;w=3600, 5000;w=86400 RateLimit-Limit: 5000, 1000;w=3600, 5000;w=86400
RateLimit-Remaining: 100 RateLimit-Remaining: 100
RateLimit-Reset: 36000 RateLimit-Reset: 36000
{"hello": "world"} {"hello": "world"}
skipping to change at line 986 skipping to change at page 22, line 20
Field name: "RateLimit-Reset" Field name: "RateLimit-Reset"
Status: permanent Status: permanent
Specification document(s): Section 3.3 of this document Specification document(s): Section 3.3 of this document
11. References 11. References
11.1. Normative References 11.1. Normative References
[CACHING] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching",
RFC 7234, DOI 10.17487/RFC7234, June 2014,
<https://www.rfc-editor.org/info/rfc7234>.
[MESSAGING]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
Protocol (HTTP/1.1): Message Syntax and Routing",
RFC 7230, DOI 10.17487/RFC7230, June 2014,
<https://www.rfc-editor.org/info/rfc7230>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997, DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>. <https://www.rfc-editor.org/info/rfc2119>.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", STD 68, RFC 5234, Specifications: ABNF", STD 68, RFC 5234,
DOI 10.17487/RFC5234, January 2008, DOI 10.17487/RFC5234, January 2008,
<https://www.rfc-editor.org/info/rfc5234>. <https://www.rfc-editor.org/info/rfc5234>.
skipping to change at line 1020 skipping to change at page 22, line 43
[RFC7405] Kyzivat, P., "Case-Sensitive String Support in ABNF", [RFC7405] Kyzivat, P., "Case-Sensitive String Support in ABNF",
RFC 7405, DOI 10.17487/RFC7405, December 2014, RFC 7405, DOI 10.17487/RFC7405, December 2014,
<https://www.rfc-editor.org/info/rfc7405>. <https://www.rfc-editor.org/info/rfc7405>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[SEMANTICS] [SEMANTICS]
Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Fielding, R., Nottingham, M., and J. Reschke, "HTTP
Protocol (HTTP/1.1): Semantics and Content", RFC 7231, Semantics", draft-ietf-httpbis-semantics-14 (work in
DOI 10.17487/RFC7231, June 2014, progress), January 2021.
<https://www.rfc-editor.org/info/rfc7231>.
[UNIX] The Open Group, ., "The Single UNIX Specification, Version [UNIX] The Open Group, ., "The Single UNIX Specification, Version
2 - 6 Vol Set for UNIX 98", February 1997. 2 - 6 Vol Set for UNIX 98", February 1997.
11.2. Informative References 11.2. Informative References
[RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
<https://www.rfc-editor.org/info/rfc3339>. <https://www.rfc-editor.org/info/rfc3339>.
skipping to change at line 1159 skipping to change at page 25, line 41
as an example of a throttled request, that could instead use even as an example of a throttled request, that could instead use even
403 or whatever status code. 403 or whatever status code.
4. Why don't pass the throttling scope as a parameter? 4. Why don't pass the throttling scope as a parameter?
After a discussion on a similar thread [3] we will probably add a After a discussion on a similar thread [3] we will probably add a
new "RateLimit-Scope" header to this spec. new "RateLimit-Scope" header to this spec.
I'm open to suggestions: comment on this issue [4] I'm open to suggestions: comment on this issue [4]
5. Why using delta-seconds instead of a UNIX Timestamp? Why not 5. Why using delay-seconds instead of a UNIX Timestamp? Why not
using subsecond precision? using subsecond precision?
Using delta-seconds aligns with "Retry-After", which is returned Using delay-seconds aligns with "Retry-After", which is returned
in similar contexts, eg on 429 responses. in similar contexts, eg on 429 responses.
delta-seconds as defined in [CACHING] section 1.2.1 clarifies
some parsing rules too.
Timestamps require a clock synchronization protocol (see Timestamps require a clock synchronization protocol (see
[SEMANTICS] section 4.1.1.1). This may be problematic (eg. clock Section 5.6.7 of [SEMANTICS]). This may be problematic (eg.
adjustment, clock skew, failure of hardcoded clock clock adjustment, clock skew, failure of hardcoded clock
synchronization servers, IoT devices, ..). Moreover timestamps synchronization servers, IoT devices, ..). Moreover timestamps
may not be monotonically increasing due to clock adjustment. See may not be monotonically increasing due to clock adjustment. See
Another NTP client failure story [5] Another NTP client failure story [5]
We did not use subsecond precision because: We did not use subsecond precision because:
* that is more subject to system clock correction like the one * that is more subject to system clock correction like the one
implemented via the adjtimex() Linux system call; implemented via the adjtimex() Linux system call;
* response-time latency may not make it worth. A brief * response-time latency may not make it worth. A brief
discussion on the subject is on the httpwg ml [6] discussion on the subject is on the httpwg ml [6]
* almost all rate-limit headers implementations do not use it. * almost all rate-limit headers implementations do not use it.
skipping to change at line 1275 skipping to change at page 28, line 7
2. Can intermediaries alter RateLimit fields? 2. Can intermediaries alter RateLimit fields?
Generally, they should not because it might result in unserviced Generally, they should not because it might result in unserviced
requests. There are reasonable use cases for intermediaries requests. There are reasonable use cases for intermediaries
mangling RateLimit fields though, e.g. when they enforce stricter mangling RateLimit fields though, e.g. when they enforce stricter
quota-policies, or when they are an active component of the quota-policies, or when they are an active component of the
service. In those case we will consider them as part of the service. In those case we will consider them as part of the
originating infrastructure. originating infrastructure.
Changes
_RFC Editor: Please remove this section before publication._
E.1. Since draft-ietf-httpapi-ratelimit-headers-00
o Use I-D.httpbis-semantics, which includes referencing "delay-
seconds" instead of "delta-seconds". #5
Authors' Addresses Authors' Addresses
Roberto Polli Roberto Polli
Team Digitale, Italian Government Team Digitale, Italian Government
Italy
Email: robipolli@gmail.com Email: robipolli@gmail.com
Alejandro Martinez Ruiz Alejandro Martinez Ruiz
Red Hat Red Hat
Email: amr@redhat.com Email: amr@redhat.com
 End of changes. 38 change blocks. 
105 lines changed or deleted 113 lines changed or added

This html diff was produced by rfcdiff 1.44jr. The latest version is available from http://tools.ietf.org/tools/rfcdiff/