draft-ietf-httpapi-ratelimit-headers-06.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 25, 2023 Red Hat | Expires: July 12, 2024 Red Hat | |||
December 22, 2022 | January 09, 2024 | |||
RateLimit Fields for HTTP | RateLimit header fields for HTTP | |||
draft-ietf-httpapi-ratelimit-headers-06 | draft-ietf-httpapi-ratelimit-headers-latest | |||
Abstract | Abstract | |||
This document defines the RateLimit-Limit, RateLimit-Remaining, | This document defines the RateLimit-Policy and RateLimit HTTP header | |||
RateLimit-Reset and RateLimit-Policy HTTP fields for servers to | fields for servers to advertise their service policy limits and the | |||
advertise their current service rate limits, thereby allowing clients | current limits, thereby allowing clients to avoid being throttled. | |||
to avoid being throttled. | ||||
About This Document | About This Document | |||
This note is to be removed before publishing as an RFC. | This note is to be removed before publishing as an RFC. | |||
Status information for this document may be found at | Status information for this document may be found at | |||
<https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit- | <https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit- | |||
headers/>. | headers/>. | |||
Discussion of this document takes place on the HTTPAPI Working Group | Discussion of this document takes place on the HTTPAPI Working Group | |||
skipping to change at line 50 ¶ | skipping to change at page 2, line 4 ¶ | |||
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 July 12, 2024. | ||||
This Internet-Draft will expire on June 25, 2023. | ||||
Copyright Notice | Copyright Notice | |||
Copyright (c) 2022 IETF Trust and the persons identified as the | Copyright (c) 2024 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. Goals | 1.1. Goals . . . . . . . . . . . . . . . . . . . . . . . . . . 4 | |||
1.2. Notational Conventions | 1.2. Notational Conventions . . . . . . . . . . . . . . . . . 5 | |||
2. Concepts | 2. Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . 5 | |||
2.1. Quota Policy | 2.1. Quota Policy . . . . . . . . . . . . . . . . . . . . . . 5 | |||
2.2. Time Window | 2.2. Service Limit . . . . . . . . . . . . . . . . . . . . . . 6 | |||
2.3. Service Limit | 2.3. Time Window . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
3. RateLimit Field Definitions | 3. RateLimit header field Definitions . . . . . . . . . . . . . 7 | |||
3.1. RateLimit-Limit | 3.1. RateLimit . . . . . . . . . . . . . . . . . . . . . . . . 7 | |||
3.2. RateLimit-Policy | 3.2. Limit Keyword . . . . . . . . . . . . . . . . . . . . . . 7 | |||
3.3. RateLimit-Remaining | 3.3. Remaining Keyword . . . . . . . . . . . . . . . . . . . . 8 | |||
3.4. RateLimit-Reset | 3.4. Reset Keyword . . . . . . . . . . . . . . . . . . . . . . 8 | |||
4. Server Behavior | 3.5. RateLimit-Policy . . . . . . . . . . . . . . . . . . . . 9 | |||
4.1. Performance Considerations | 4. Server Behavior . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
5. Client Behavior | 4.1. Performance Considerations . . . . . . . . . . . . . . . 10 | |||
5.1. Intermediaries | 5. Client Behavior . . . . . . . . . . . . . . . . . . . . . . . 11 | |||
5.2. Caching | 5.1. Intermediaries . . . . . . . . . . . . . . . . . . . . . 12 | |||
6. Security Considerations | 5.2. Caching . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
6.1. Throttling does not prevent clients from issuing requests | 6. Security Considerations . . . . . . . . . . . . . . . . . . . 13 | |||
6.2. Information disclosure | 6.1. Throttling does not prevent clients from issuing requests 13 | |||
6.3. Remaining quota units are not granted requests | 6.2. Information disclosure . . . . . . . . . . . . . . . . . 13 | |||
6.4. Reliability of RateLimit-Reset | 6.3. Remaining quota units are not granted requests . . . . . 13 | |||
6.5. Resource exhaustion | 6.4. Reliability of the reset keyword . . . . . . . . . . . . 13 | |||
6.5.1. Denial of Service | 6.5. Resource exhaustion . . . . . . . . . . . . . . . . . . . 14 | |||
7. Privacy Considerations | 6.5.1. Denial of Service . . . . . . . . . . . . . . . . . . 14 | |||
8. IANA Considerations | 7. Privacy Considerations . . . . . . . . . . . . . . . . . . . 15 | |||
8.1. RateLimit Parameters Registration | 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15 | |||
9. References | 8.1. RateLimit Keywords and Parameters Registration . . . . . 16 | |||
9.1. Normative References | 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 17 | |||
9.2. Informative References | 9.1. Normative References . . . . . . . . . . . . . . . . . . 17 | |||
9.3. URIs | 9.2. Informative References . . . . . . . . . . . . . . . . . 18 | |||
Appendix A. Rate-limiting and quotas | 9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 18 | |||
A.1. Interoperability issues | Appendix A. Rate-limiting and quotas . . . . . . . . . . . . . . 19 | |||
Appendix B. Examples | A.1. Interoperability issues . . . . . . . . . . . . . . . . . 20 | |||
B.1. Unparameterized responses | Appendix B. Examples . . . . . . . . . . . . . . . . . . . . . . 20 | |||
B.1.1. Throttling information in responses | B.1. Unparameterized responses . . . . . . . . . . . . . . . . 20 | |||
B.1.2. Use in conjunction with custom fields | B.1.1. Throttling information in responses . . . . . . . . . 20 | |||
B.1.3. Use for limiting concurrency | B.1.2. Use in conjunction with custom fields . . . . . . . . 21 | |||
B.1.4. Use in throttled responses | B.1.3. Use for limiting concurrency . . . . . . . . . . . . 22 | |||
B.2. Parameterized responses | B.1.4. Use in throttled responses . . . . . . . . . . . . . 23 | |||
B.2.1. Throttling window specified via parameter | B.2. Parameterized responses . . . . . . . . . . . . . . . . . 23 | |||
B.2.2. Dynamic limits with parameterized windows | B.2.1. Throttling window specified via parameter . . . . . . 24 | |||
B.2.3. Dynamic limits for pushing back and slowing down | B.2.2. Dynamic limits with parameterized windows . . . . . . 24 | |||
B.2.3. Dynamic limits for pushing back and slowing down . . 25 | ||||
B.3. Dynamic limits for pushing back with Retry-After and slow | B.3. Dynamic limits for pushing back with Retry-After and slow | |||
down | down . . . . . . . . . . . . . . . . . . . . . . . . . . 25 | |||
B.3.1. Missing Remaining information | B.3.1. Missing Remaining information . . . . . . . . . . . . 26 | |||
B.3.2. Use with multiple windows | B.3.2. Use with multiple windows . . . . . . . . . . . . . . 27 | |||
FAQ | FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 | |||
RateLimit fields currently used on the web | RateLimit header fields currently used on the web . . . . . . . . 31 | |||
Acknowledgements | Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 33 | |||
Changes | Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 | |||
F.1. Since draft-ietf-httpapi-ratelimit-headers-03 | F.1. Since draft-ietf-httpapi-ratelimit-headers-03 . . . . . . 33 | |||
F.2. Since draft-ietf-httpapi-ratelimit-headers-02 | F.2. Since draft-ietf-httpapi-ratelimit-headers-02 . . . . . . 33 | |||
F.3. Since draft-ietf-httpapi-ratelimit-headers-01 | F.3. Since draft-ietf-httpapi-ratelimit-headers-01 . . . . . . 33 | |||
F.4. Since draft-ietf-httpapi-ratelimit-headers-00 | F.4. Since draft-ietf-httpapi-ratelimit-headers-00 . . . . . . 33 | |||
Authors' Addresses | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 34 | |||
1. Introduction | 1. Introduction | |||
Rate limiting HTTP clients has become a widespread practice, | Rate limiting HTTP clients has become a widespread practice, | |||
especially for HTTP APIs. Typically, servers who do so limit the | especially for HTTP APIs. Typically, servers who do so limit the | |||
number of acceptable requests in a given time window (e.g. 10 | number of acceptable requests in a given time window (e.g. 10 | |||
requests per second). See Appendix A for further information on the | requests per second). See Appendix A for further information on the | |||
current usage of rate limiting in HTTP. | current usage of rate limiting in HTTP. | |||
Currently, there is no standard way for servers to communicate quotas | Currently, there is no standard way for servers to communicate quotas | |||
so that clients can throttle its requests to prevent errors. This | so that clients can throttle its requests to prevent errors. This | |||
document defines a set of standard HTTP fields to enable rate | document defines a set of standard HTTP header fields to enable rate | |||
limiting: | limiting: | |||
o RateLimit-Limit: the server's quota for requests by the client in | o RateLimit: to convey the server's current limit of quota units | |||
the time window, | available to the client in the policy time window, the remaining | |||
quota units in the current window, and the time remaining in the | ||||
o RateLimit-Remaining: the remaining quota in the current window, | current window, specified in seconds, and | |||
o RateLimit-Reset: the time remaining in the current window, | ||||
specified in seconds, and | ||||
o RateLimit-Policy: the quota policy. | o RateLimit-Policy: the service policy limits. | |||
These fields allow the establishment of complex rate limiting | These fields allow the establishment of complex rate limiting | |||
policies, including using multiple and variable time windows and | policies, including using multiple and variable time windows and | |||
dynamic quotas, and implementing concurrency limits. | dynamic quotas, and implementing concurrency limits. | |||
The behavior of the RateLimit-Reset field is compatible with the | The behavior of the RateLimit header field is compatible with the | |||
delay-seconds notation of Retry-After. | delay-seconds notation of Retry-After. | |||
1.1. Goals | 1.1. Goals | |||
The goals of this document are: | The goals of this document are: | |||
Interoperability: Standardization of the names and semantics of | Interoperability: Standardization of the names and semantics of | |||
rate-limit headers to ease their enforcement and adoption; | rate-limit headers to ease their enforcement and adoption; | |||
Resiliency: Improve resiliency of HTTP infrastructure by providing | Resiliency: Improve resiliency of HTTP infrastructure by providing | |||
clients with information useful to throttle their requests and | clients with information useful to throttle their requests and | |||
prevent 4xx or 5xx responses; | prevent 4xx or 5xx responses; | |||
Documentation: Simplify API documentation by eliminating the need to | Documentation: Simplify API documentation by eliminating the need to | |||
include detailed quota limits and related fields in API | include detailed quota limits and related fields in API | |||
documentation. | documentation. | |||
The following features are out of the scope of this document: | The following features are out of the scope of this document: | |||
Authorization: RateLimit fields are not meant to support | Authorization: RateLimit header fields are not meant to support | |||
authorization or other kinds of access controls. | 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 (see Section 7 of [WEB-ORIGIN]). This can be | the whole Origin (see Section 7 of [WEB-ORIGIN]). This can be | |||
addressed using extensibility mechanisms such as the parameter | addressed using extensibility mechanisms such as the parameter | |||
registry Section 8.1. | registry Section 8.1. | |||
Response status code: RateLimit fields may be returned in both | Response status code: RateLimit header fields may be returned in | |||
successful (see Section 15.3 of [HTTP]) and non-successful | both successful (see Section 15.3 of [HTTP]) and non-successful | |||
responses. This specification does not cover whether non | responses. This specification does not cover whether non | |||
Successful responses count on quota usage, nor it mandates any | Successful responses count on quota usage, nor it mandates any | |||
correlation between the RateLimit values and the returned status | correlation between the RateLimit values and the returned status | |||
code. | code. | |||
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 fields, including | throttling policy. The values published in the fields, 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 217 ¶ | skipping to change at page 5, line 24 ¶ | |||
by [RFC7405] along with the "#rule" extension defined in | by [RFC7405] along with the "#rule" extension defined in | |||
Section 5.6.1 of [HTTP]. | Section 5.6.1 of [HTTP]. | |||
The term Origin is to be interpreted as described in Section 7 of | The term Origin is to be interpreted as described in Section 7 of | |||
[WEB-ORIGIN]. | [WEB-ORIGIN]. | |||
This document uses the terms List, Item and Integer from Section 3 of | This document uses the terms List, Item and Integer from Section 3 of | |||
[STRUCTURED-FIELDS] to specify syntax and parsing, along with the | [STRUCTURED-FIELDS] to specify syntax and parsing, along with the | |||
concept of "bare item". | concept of "bare item". | |||
The fields defined in this document are collectively referred to as | The header fields defined in this document are collectively referred | |||
"RateLimit fields". | to as "RateLimit header fields". | |||
2. Concepts | 2. Concepts | |||
2.1. Quota Policy | 2.1. Quota Policy | |||
A quota policy is described in terms of quota units (Section 2.3) and | A quota policy is maintained by a server to limit the activity | |||
a time window (Section 2.2). It is an Item whose bare item is a | (counted in quota units) of a given client over a period of time | |||
service limit (Section 2.3), along with associated Parameters. | (known as the time window (Section 2.3)) to a specified amount (known | |||
as the service limit (Section 2.2)). | ||||
The following parameters are defined in this specification: | ||||
w: The REQUIRED "w" parameter value conveys a time window value as | ||||
defined in Section 2.2. | ||||
Other parameters are allowed and can be regarded as comments. They | Quota policies can be advertised by servers (see Section 3.5), but | |||
ought to be registered within the "Hypertext Transfer Protocol (HTTP) | they are not required to be, and more than one quota policy can | |||
RateLimit Parameters Registry", as described in Section 8.1. | affect a given request from a client to a server. | |||
For example, a quota policy of 100 quota units per minute: | A quota policy is expressed in Structured Fields [STRUCTURED-FIELDS] | |||
as an Integer that indicates the service limit with associated | ||||
parameters. | ||||
100;w=60 | The following Parameters are defined in this specification: | |||
The definition of a quota policy does not imply any specific | w: The REQUIRED "w" parameter value conveys a time window | |||
distribution of quota units within the time window. If applicable, | (Section 2.3). | |||
these details can be conveyed as extension parameters. | ||||
For example, two quota policies containing further details via | For example, a quota policy of 100 quota units per minute is | |||
extension parameters: | expressed as: | |||
100;w=60;comment="fixed window" | 100;w=60 | |||
12;w=1;burst=1000;policy="leaky bucket" | ||||
To avoid clashes, implementers SHOULD prefix unregistered parameters | Other parameters are allowed and can be regarded as comments. | |||
with a vendor identifier, e.g. "acme-policy", "acme-burst". While it | Parameters for use by more than one implementation or service ought | |||
is useful to define a clear syntax and semantics even for custom | to be registered within the "Hypertext Transfer Protocol (HTTP) | |||
parameters, it is important to note that user agents are not required | RateLimit Parameters Registry", as described in Section 8.1. | |||
to process quota policy information. | ||||
2.2. Time Window | Implementation- or service-specific parameters SHOULD be prefixed | |||
parameters with a vendor identifier, e.g. "acme-policy", "acme- | ||||
burst". | ||||
Rate limit policies limit the number of acceptable requests within a | 2.2. Service Limit | |||
given time interval, known as a time window. | ||||
The time window is a non-negative Integer value expressing that | The service limit is a non-negative Integer indicating the maximum | |||
interval in seconds, similar to the "delay-seconds" rule defined in | amount of activity that the server is willing to accept from what it | |||
Section 10.2.3 of [HTTP]. Subsecond precision is not supported. | identifies as the client (e.g., based upon originating IP or user | |||
authentication) during a time window (Section 2.3). | ||||
2.3. Service Limit | The activity being limited is usually the HTTP requests made by the | |||
client; for example "you can make 100 requests per minute". However, | ||||
a server might only rate limit some requests (based upon URI, method, | ||||
user identity, etc.), and it might weigh requests differently. | ||||
Therefore, quota policies are defined in terms of "quota units". | ||||
Servers SHOULD document how they count quota units. | ||||
The service limit is associated with the maximum number of requests | For example, a server could count requests like "/books/{id}" once, | |||
that the server is willing to accept from one or more clients on a | but count search requests like "/books?author=WuMing" twice. This | |||
given basis (originating IP, authenticated user, geographical, ..) | might result in the following counters: | |||
during a time window (Section 2.2). | ||||
The service limit is a non-negative Integer expressed in quota units. | GET /books/123 ; service-limit=4, remaining: 3, status=200 | |||
GET /books?author=WuMing ; service-limit=4, remaining: 1, status=200 | ||||
GET /books?author=Eco ; service-limit=4, remaining: 0, status=429 | ||||
The service limit SHOULD match the maximum number of acceptable | Often, the service limit advertised will match the server's actual | |||
requests. However, the service limit MAY differ from the total | limit. However, it MAY differ when weight mechanisms, bursts, or | |||
number of acceptable requests when weight mechanisms, bursts, or | other server policies are implemented. In that case the difference | |||
other server policies are implemented. | SHOULD be communicated using an extension or documented separately. | |||
If the service limit does not match the maximum number of acceptable | 2.3. Time Window | |||
requests the relation with that SHOULD be communicated out-of-band. | ||||
Example: A server could | Quota policies limit the number of acceptable requests within a given | |||
time interval, known as a time window. | ||||
o count once requests like "/books/{id}" | The time window is a non-negative Integer value expressing that | |||
interval in seconds, similar to the "delay-seconds" rule defined in | ||||
Section 10.2.3 of [HTTP]. Subsecond precision is not supported. | ||||
o count twice search requests like "/books?author=WuMing" | By default, a quota policy does not constrain the distribution of | |||
quota units within the time window. If necessary, these details can | ||||
be conveyed as extension parameters. | ||||
so that we have the following counters | For example, two quota policies containing further details via | |||
extension parameters: | ||||
GET /books/123 ; service-limit=4, remaining: 3, status=200 | 100;w=60;comment="fixed window" | |||
GET /books?author=WuMing ; service-limit=4, remaining: 1, status=200 | 12;w=1;burst=1000;policy="leaky bucket" | |||
GET /books?author=Eco ; service-limit=4, remaining: 0, status=429 | ||||
3. RateLimit Field Definitions | 3. RateLimit header field Definitions | |||
The following RateLimit response fields are defined. | The following RateLimit response header fields are defined. | |||
3.1. RateLimit-Limit | 3.1. RateLimit | |||
The "RateLimit-Limit" response field indicates the service limit | A server uses the "RateLimit" response header field to communicate | |||
(Section 2.3) associated with the client in the current time window | its quota policies. | |||
(Section 2.2). If the client exceeds that limit, it MAY not be | ||||
served. | ||||
The field is an Item and its value is a non-negative Integer referred | The field is a Dictionary. The allowed keys are defined in the | |||
to as the "expiring-limit". This specification does not define | "Hypertext Transfer Protocol (HTTP) RateLimit Keywords and Parameters | |||
Parameters for this field. If they appear, they MUST be ignored. | Registry", as described in Section 8.1. | |||
The expiring-limit MUST be set to the service limit that is closest | The following Keys are defined in this specification: | |||
to reaching its limit, and the associated time window MUST either be: | ||||
o inferred by the value of RateLimit-Reset field at the moment of | limit: The REQUIRED "limit" key value conveys the expiring limit | |||
the reset, or | (Section 3.2). remaining: | |||
o communicated out-of-band (e.g. in the documentation). | The OPTIONAL "remaining" key value conveys the remaining quota | |||
units (Section 3.3). reset: | ||||
The RateLimit-Policy field (see Section 3.2), might contain | The REQUIRED "reset" key value conveys the time window reset time | |||
information on the associated time window. | (Section 3.4). | |||
RateLimit-Limit: 100 | This specification does not define Parameters for this field. If | |||
they appear, they MUST be ignored. | ||||
This field can be sent in a trailer section. | This field cannot appear in a trailer section. | |||
3.2. RateLimit-Policy | 3.2. Limit Keyword | |||
The "RateLimit-Policy" response field indicates the quota policies | The "limit" keyword indicates the service limit (Section 2.2) | |||
currently associated with the client. Its value is informative. | associated with the client in the current time window (Section 2.3). | |||
If the client exceeds that limit, it MAY not be served. | ||||
The field is a non-empty List of Items. Each item is a quota policy | It is an Item and its value is a non-negative Integer referred to as | |||
(Section 2.1). | the "expiring limit". This specification does not define Parameters | |||
for it. If they appear, they MUST be ignored. | ||||
This field can convey the time window associated with the expiring- | The expiring limit MUST be set to the service limit that is closest | |||
limit, as shown in this example: | to reaching its limit, and the associated time window MUST either be: | |||
RateLimit-Policy: 100;w=10 | o inferred by the value of the reset keyword (Section 3.4) at the | |||
RateLimit-Limit: 100 | moment of the reset, or | |||
These examples show multiple policies being returned: | o communicated out-of-band (e.g. in the documentation). | |||
RateLimit-Policy: 10;w=1, 50;w=60, 1000;w=3600, 5000;w=86400 | Example: | |||
RateLimit-Policy: 10;w=1;burst=1000, 1000;w=3600 | ||||
This field can be sent in a trailer section. | limit=100 | |||
3.3. RateLimit-Remaining | The RateLimit-Policy header field (see Section 3.5), might contain | |||
information on the associated time window. | ||||
The "RateLimit-Remaining" response field indicates the remaining | 3.3. Remaining Keyword | |||
quota units associated to the expiring-limit. | ||||
The field is an Item and its value is a non-negative Integer | The "remaining" keyword indicates the remaining quota units | |||
expressed in quota units (Section 2.3). This specification does not | associated with the expiring-limit. | |||
define Parameters for this field. If they appear, they MUST be | ||||
ignored. | ||||
This field can be sent in a trailer section. | It is an Item and its value is a non-negative Integer expressed in | |||
quota units (Section 2.2). This specification does not define | ||||
Parameters for it. If they appear, they MUST be ignored. | ||||
Clients MUST NOT assume that a positive RateLimit-Remaining field | Clients MUST NOT assume that a positive remaining value is a | |||
value is a guarantee that further requests will be served. | guarantee that further requests will be served. | |||
When the value of RateLimit-Remaining is low, it indicates that the | When the value of the remaining keyword is low, it indicates that the | |||
server may soon throttle the client (see Section 4). | server may soon throttle the client (see Section 4). | |||
For example: | For example: | |||
RateLimit-Remaining: 50 | remaining=50 | |||
3.4. RateLimit-Reset | 3.4. Reset Keyword | |||
The "RateLimit-Reset" field response field indicates the number of | The "reset" keyword indicates the number of seconds until the | |||
seconds until the quota associated to the expiring-limit resets. | available quota units associated with the expiring-limit resets. | |||
The field is a non-negative Integer compatible with the delay-seconds | It is a non-negative Integer compatible with the delay-seconds rule, | |||
rule, because: | 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 | |||
Section 5.6.7 of [HTTP]); | Section 5.6.7 of [HTTP]); | |||
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 specification does not define Parameters for this field. If | This specification does not define Parameters for it. If they | |||
they appear, they MUST be ignored. | appear, they MUST be ignored. | |||
This field can be sent in a trailer section. | ||||
An example of RateLimit-Reset field use is below. | For example: | |||
RateLimit-Reset: 50 | reset=50 | |||
The client MUST NOT assume that all its service limit will be reset | The client MUST NOT assume that all its service limit will be reset | |||
at the moment indicated by the RateLimit-Reset field. The server MAY | at the moment indicated by the reset keyword. The server MAY | |||
arbitrarily alter the RateLimit-Reset field value between subsequent | arbitrarily alter the reset keyword value between subsequent | |||
requests; for example, in case of resource saturation or to implement | requests; for example, in case of resource saturation or to implement | |||
sliding window policies. | sliding window policies. | |||
3.5. RateLimit-Policy | ||||
The "RateLimit-Policy" response header field indicates a service | ||||
policy currently associated with the client. Its value is | ||||
informative. | ||||
The field is a non-empty List of Items. Each item is a quota policy | ||||
(Section 2.1). Two quota policies MUST NOT be associated with the | ||||
same quota units value. | ||||
This field can convey the time window associated with the expiring- | ||||
limit, as shown in this example: | ||||
RateLimit-Policy: 100;w=10 | ||||
RateLimit: limit=100, remaining=50, reset=5 | ||||
These examples show multiple policies being returned: | ||||
RateLimit-Policy: 10;w=1, 50;w=60, 1000;w=3600, 5000;w=86400 | ||||
RateLimit-Policy: 10;w=1;burst=1000, 1000;w=3600 | ||||
An example of invalid header field value with two policies associated | ||||
with the same quota units: | ||||
RateLimit-Policy: 10;w=1, 10;w=60 | ||||
This field cannot appear in a trailer section. | ||||
4. Server Behavior | 4. Server Behavior | |||
A server uses the RateLimit fields to communicate its quota policies. | A server uses the RateLimit header fields to communicate its quota | |||
Sending the RateLimit-Limit and RateLimit-Reset fields is REQUIRED; | policies. A response that includes the RateLimit-Limit header field | |||
sending RateLimit-Remaining field is RECOMMENDED. | MUST also include the RateLimit-Reset. It MAY also include a | |||
RateLimit-Remaining header field. | ||||
A server MAY return RateLimit fields independently of the response | A server MAY return RateLimit header fields independently of the | |||
status code. This includes on throttled responses. This document | response status code. This includes on throttled responses. This | |||
does not mandate any correlation between the RateLimit field values | document does not mandate any correlation between the RateLimit | |||
and the returned status code. | header field values and the returned status code. | |||
Servers should be careful when returning RateLimit fields in | Servers should be careful when returning RateLimit header fields in | |||
redirection responses (i.e., responses with 3xx status codes) because | redirection responses (i.e., responses with 3xx status codes) because | |||
a low RateLimit-Remaining field value could prevent the client from | a low remaining keyword value could prevent the client from issuing | |||
issuing requests. For example, given the RateLimit fields below, a | requests. For example, given the RateLimit header fields below, a | |||
client could decide to wait 10 seconds before following the | client could decide to wait 10 seconds before following the | |||
"Location" header field (see Section 10.2.2 of [HTTP]), because the | "Location" header field (see Section 10.2.2 of [HTTP]), because the | |||
RateLimit-Remaining field value is 0. | remaining keyword value is 0. | |||
HTTP/1.1 301 Moved Permanently | HTTP/1.1 301 Moved Permanently | |||
Location: /foo/123 | Location: /foo/123 | |||
RateLimit-Remaining: 0 | RateLimit: limit=10, remaining=0, reset=10 | |||
RateLimit-Limit: 10 | ||||
RateLimit-Reset: 10 | ||||
If a response contains both the Retry-After and the RateLimit-Reset | If a response contains both the Retry-After and the RateLimit header | |||
fields, the RateLimit-Reset field value SHOULD reference the same | fields, the reset keyword value SHOULD reference the same point in | |||
point in time as the Retry-After field value. | time as the Retry-After field value. | |||
When using a policy involving more than one time window, the server | When using a policy involving more than one time window, the server | |||
MUST reply with the RateLimit fields related to the time window with | MUST reply with the RateLimit header fields related to the time | |||
the lower RateLimit-Remaining field values. | window with the lower remaining keyword values. | |||
A service using RateLimit fields MUST NOT convey values exposing an | A service using RateLimit header fields MUST NOT convey values | |||
unwanted volume of requests and SHOULD implement mechanisms to cap | exposing an unwanted volume of requests and SHOULD implement | |||
the ratio between RateLimit-Remaining and RateLimit-Reset field | mechanisms to cap the ratio between the remaining and the reset | |||
values (see Section 6.5); this is especially important when a quota | keyword values (see Section 6.5); this is especially important when a | |||
policy uses a large time window. | quota policy uses a large time window. | |||
Under certain conditions, a server MAY artificially lower RateLimit | Under certain conditions, a server MAY artificially lower RateLimit | |||
field values between subsequent requests, e.g. to respond to Denial | header field values between subsequent requests, e.g. to respond to | |||
of Service attacks or in case of resource saturation. | Denial of Service attacks or in case of resource saturation. | |||
Servers usually establish whether the request is in-quota before | ||||
creating a response, so the RateLimit field values should be already | ||||
available in that moment. Nonetheless servers MAY decide to send the | ||||
RateLimit fields in a trailer section. | ||||
4.1. Performance Considerations | 4.1. Performance Considerations | |||
Servers are not required to return RateLimit fields in every | Servers are not required to return RateLimit header fields in every | |||
response, and clients need to take this into account. For example, | response, and clients need to take this into account. For example, | |||
an implementer concerned with performance might provide RateLimit | an implementer concerned with performance might provide RateLimit | |||
fields only when a given quota is going to expire. | header fields only when a given quota is going to expire. | |||
Implementers concerned with response fields' size, might take into | Implementers concerned with response fields' size, might take into | |||
account their ratio with respect to the content length, or use | account their ratio with respect to the content length, or use | |||
header-compression HTTP features such as [HPACK]. | header-compression HTTP features such as [HPACK]. | |||
5. Client Behavior | 5. Client Behavior | |||
The RateLimit fields can be used by clients to determine whether the | The RateLimit header fields can be used by clients to determine | |||
associated request respected the server's quota policy, and as an | whether the associated request respected the server's quota policy, | |||
indication of whether subsequent requests will. However, the server | and as an indication of whether subsequent requests will. However, | |||
might apply other criteria when servicing future requests, and so the | the server might apply other criteria when servicing future requests, | |||
quota policy may not completely reflect whether they will succeed. | and so the quota policy may not completely reflect whether they will | |||
succeed. | ||||
For example, a successful response with the following fields: | For example, a successful response with the following fields: | |||
RateLimit-Limit: 10 | RateLimit: limit=10, remaining=1, reset=7 | |||
RateLimit-Remaining: 1 | ||||
RateLimit-Reset: 7 | ||||
does not guarantee that the next request will be successful. | does not guarantee that the next request will be successful. | |||
Servers' behavior may be subject to other conditions like the one | Servers' behavior may be subject to other conditions like the one | |||
shown in the example from Section 2.3. | shown in the example from Section 2.2. | |||
A client MUST validate the RateLimit fields before using them and | A client is responsible for ensuring that RateLimit header field | |||
check if there are significant discrepancies with the expected ones. | values returned cause reasonable client behavior with respect to | |||
This includes a RateLimit-Reset field moment too far in the future | throughput and latency (see Section 6.5 and Section 6.5.1). | |||
(e.g. similarly to receiving "Retry-after: 1000000") or a service- | ||||
limit too high. | ||||
A client receiving RateLimit fields MUST NOT assume that future | A client receiving RateLimit header fields MUST NOT assume that | |||
responses will contain the same RateLimit fields, or any RateLimit | future responses will contain the same RateLimit header fields, or | |||
fields at all. | any RateLimit header fields at all. | |||
Malformed RateLimit fields MUST be ignored. | Malformed RateLimit header fields MUST be ignored. | |||
A client SHOULD NOT exceed the quota units conveyed by the RateLimit- | A client SHOULD NOT exceed the quota units conveyed by the remaining | |||
Remaining field before the time window expressed in RateLimit-Reset | keyword before the time window expressed in the reset keyword. | |||
field. | ||||
A client MAY still probe the server if the RateLimit-Reset field is | A client MAY still probe the server if the reset keyword is | |||
considered too high. | considered too high. | |||
The value of RateLimit-Reset field is generated at response time: a | The value of the reset keyword is generated at response time: a | |||
client aware of a significant network latency MAY behave accordingly | client aware of a significant network latency MAY behave accordingly | |||
and use other information (e.g. the "Date" response header field, or | and use other information (e.g. the "Date" response header field, or | |||
otherwise gathered metrics) to better estimate the RateLimit-Reset | otherwise gathered metrics) to better estimate the reset keyword | |||
field moment intended by the server. | moment intended by the server. | |||
The details provided in RateLimit-Policy field are informative and | The details provided in the RateLimit-Policy header field are | |||
MAY be ignored. | informative and MAY be ignored. | |||
If a response contains both the RateLimit-Reset and Retry-After | If a response contains both the RateLimit and Retry-After fields, the | |||
fields, the Retry-After field MUST take precedence and the RateLimit- | Retry-After field MUST take precedence and the reset keyword MAY be | |||
Reset field MAY be ignored. | ignored. | |||
This specification does not mandate a specific throttling behavior | This specification does not mandate a specific throttling behavior | |||
and implementers can adopt their preferred policies, including: | and implementers can adopt their preferred policies, including: | |||
o slowing down or preemptively back-off their request rate when | o slowing down or preemptively back-off their request rate when | |||
approaching quota limits; | approaching quota limits; | |||
o consuming all the quota according to the exposed limits and then | o consuming all the quota according to the exposed limits and then | |||
wait. | wait. | |||
5.1. Intermediaries | 5.1. Intermediaries | |||
This section documents the considerations advised in Section 16.3.2 | This section documents the considerations advised in Section 16.3.2 | |||
of [HTTP]. | of [HTTP]. | |||
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 header fields' | |||
such a way as to communicate a more permissive quota policy; this | values in such a way as to communicate a more permissive quota | |||
includes removing the RateLimit fields. | policy; this includes removing the RateLimit header fields. | |||
An intermediary MAY alter the RateLimit fields in such a way as to | An intermediary MAY alter the RateLimit header fields in such a way | |||
communicate a more restrictive quota policy when: | as to communicate a more restrictive quota policy when: | |||
o it is aware of the quota unit semantic used by the Origin Server; | o it is aware of the quota unit semantic used by the Origin Server; | |||
o it implements this specification and enforces a quota policy which | o it implements this specification and enforces a quota policy which | |||
is more restrictive than the one conveyed in the fields. | is more restrictive than the one conveyed in the fields. | |||
An intermediary SHOULD forward a request even when presuming that it | An intermediary SHOULD forward a request even when presuming that it | |||
might not be serviced; the service returning the RateLimit fields is | might not be serviced; the service returning the RateLimit header | |||
the sole responsible of enforcing the communicated quota policy, and | fields is the sole responsible of enforcing the communicated quota | |||
it is always free to service incoming requests. | policy, and it is always free to service incoming requests. | |||
This specification does not mandate any behavior on intermediaries | This specification does not mandate any behavior on intermediaries | |||
respect to retries, nor requires that intermediaries have any role in | respect to retries, nor requires that intermediaries have any role in | |||
respecting quota policies. For example, it is legitimate for a proxy | respecting quota policies. For example, it is legitimate for a proxy | |||
to retransmit a request without notifying the client, and thus | to retransmit a request without notifying the client, and thus | |||
consuming quota units. | consuming quota units. | |||
Privacy considerations (Section 7) provide further guidance on | Privacy considerations (Section 7) provide further guidance on | |||
intermediaries. | intermediaries. | |||
5.2. Caching | 5.2. Caching | |||
[HTTP-CACHING] defines how responses can be stored and reused for | [HTTP-CACHING] defines how responses can be stored and reused for | |||
subsequent requests, including those with RateLimit fields. Because | subsequent requests, including those with RateLimit header fields. | |||
the information in RateLimit fields on a cached response may not be | Because the information in RateLimit header fields on a cached | |||
current, they SHOULD be ignored on responses that come from cache | response may not be current, they SHOULD be ignored on responses that | |||
(i.e., those with a positive current_age; see Section 4.2.3 of | come from cache (i.e., those with a positive current_age; see | |||
[HTTP-CACHING]). | Section 4.2.3 of [HTTP-CACHING]). | |||
6. Security Considerations | 6. Security Considerations | |||
6.1. Throttling does not prevent clients from issuing requests | 6.1. Throttling does not prevent clients from issuing requests | |||
This specification does not prevent clients from making requests. | This specification does not prevent clients from making requests. | |||
Servers should always implement mechanisms to prevent resource | Servers should always implement mechanisms to prevent resource | |||
exhaustion. | exhaustion. | |||
6.2. Information disclosure | 6.2. Information disclosure | |||
skipping to change at line 579 ¶ | skipping to change at page 13, line 26 ¶ | |||
information that can be used to saturate its infrastructural | information that can be used to saturate its infrastructural | |||
resources. | resources. | |||
While this specification does not mandate whether non-successful | While this specification does not mandate whether non-successful | |||
responses consume quota, if error responses (such as 401 | responses consume quota, if error responses (such as 401 | |||
(Unauthorized) and 403 (Forbidden)) count against quota, a malicious | (Unauthorized) and 403 (Forbidden)) count against quota, a malicious | |||
client could probe the endpoint to get traffic information of another | client could probe the endpoint to get traffic information of another | |||
user. | user. | |||
As intermediaries might retransmit requests and consume quota units | As intermediaries might retransmit requests and consume quota units | |||
without prior knowledge of the user agent, RateLimit fields might | without prior knowledge of the user agent, RateLimit header fields | |||
reveal the existence of an intermediary to the user agent. | might reveal the existence of an intermediary to the user agent. | |||
6.3. Remaining quota units are not granted requests | 6.3. Remaining quota units are not granted requests | |||
RateLimit fields convey hints from the server to the clients in order | RateLimit header fields convey hints from the server to the clients | |||
to help them avoid being throttled out. | in order to help them avoid being throttled out. | |||
Clients MUST NOT consider the quota units (Section 2.3) returned in | Clients MUST NOT consider the quota units (Section 2.2) returned in | |||
RateLimit-Remaining field as a service level agreement. | remaining keyword as a service level agreement. | |||
In case of resource saturation, the server MAY artificially lower the | In case of resource saturation, the server MAY artificially lower the | |||
returned values or not serve the request regardless of the advertised | returned values or not serve the request regardless of the advertised | |||
quotas. | quotas. | |||
6.4. Reliability of RateLimit-Reset | 6.4. Reliability of the reset keyword | |||
Consider that service limit might not be restored after the moment | Consider that service limit might not be restored after the moment | |||
referenced by RateLimit-Reset field, and the RateLimit-Reset field | referenced by the reset keyword (Section 3.4), and the reset keyword | |||
value may not be fixed nor constant. | value may not be fixed nor constant. | |||
Subsequent requests might return a higher RateLimit-Reset field value | Subsequent requests might return a higher reset keyword value to | |||
to limit concurrency or implement dynamic or adaptive throttling | limit concurrency or implement dynamic or adaptive throttling | |||
policies. | policies. | |||
6.5. Resource exhaustion | 6.5. Resource exhaustion | |||
When returning RateLimit-Reset field you must be aware that many | When returning reset keyword you must be aware that many throttled | |||
throttled clients may come back at the very moment specified. | clients may come back at the very moment specified. | |||
This is true for Retry-After too. | This is true for Retry-After too. | |||
For example, if the quota resets every day at "18:00:00" and your | For example, if the quota resets every day at "18:00:00" and your | |||
server returns the RateLimit-Reset field accordingly | server returns the reset keyword accordingly | |||
Date: Tue, 15 Nov 1994 08:00:00 GMT | Date: Tue, 15 Nov 1994 08:00:00 GMT | |||
RateLimit-Reset: 36000 | RateLimit: limit=1, remaining=1, reset=36000 | |||
there's a high probability that all clients will show up at | there's a high probability that all clients will show up at | |||
"18:00:00". | "18:00:00". | |||
This could be mitigated by adding some jitter to the field-value. | This could be mitigated by adding some jitter to the field-value. | |||
Resource exhaustion issues can be associated with quota policies | Resource exhaustion issues can be associated with quota policies | |||
using a large time window, because a user agent by chance or on | using a large time window, because a user agent by chance or on | |||
purpose might consume most of its quota units in a significantly | purpose might consume most of its quota units in a significantly | |||
shorter interval. | shorter interval. | |||
This behavior can be even triggered by the provided RateLimit fields. | This behavior can be even triggered by the provided RateLimit header | |||
The following example describes a service with an unconsumed quota | fields. The following example describes a service with an unconsumed | |||
policy of 10000 quota units per 1000 seconds. | quota policy of 10000 quota units per 1000 seconds. | |||
RateLimit-Limit: 10000 | RateLimit: limit=10000, remaining=10000, reset=10 | |||
RateLimit-Policy: 10000;w=1000 | RateLimit-Policy: 10000;w=1000 | |||
RateLimit-Remaining: 10000 | ||||
RateLimit-Reset: 10 | ||||
A client implementing a simple ratio between RateLimit-Remaining | A client implementing a simple ratio between remaining keyword and | |||
field and RateLimit-Reset field could infer an average throughput of | reset keyword could infer an average throughput of 1000 quota units | |||
1000 quota units per second, while the RateLimit-Limit field conveys | per second, while the limit keyword conveys a quota-policy with an | |||
a quota-policy with an average of 10 quota units per second. If the | average of 10 quota units per second. If the service cannot handle | |||
service cannot handle such load, it should return either a lower | such load, it should return either a lower remaining keyword value or | |||
RateLimit-Remaining field value or an higher RateLimit-Reset field | an higher reset keyword value. Moreover, complementing large time | |||
value. Moreover, complementing large time window quota policies with | window quota policies with a short time window one mitigates those | |||
a short time window one mitigates those risks. | risks. | |||
6.5.1. Denial of Service | 6.5.1. Denial of Service | |||
RateLimit fields may contain unexpected values by chance or on | RateLimit header fields may contain unexpected values by chance or on | |||
purpose. For example, an excessively high RateLimit-Remaining field | purpose. For example, an excessively high remaining keyword value | |||
value may be: | may be: | |||
o used by a malicious intermediary to trigger a Denial of Service | o used by a malicious intermediary to trigger a Denial of Service | |||
attack or consume client resources boosting its requests; | attack or consume client resources boosting its requests; | |||
o passed by a misconfigured server; | o passed by a misconfigured server; | |||
or a high RateLimit-Reset field value could inhibit clients to | or a high reset keyword value could inhibit clients to contact the | |||
contact the server. | server (e.g. similarly to receiving "Retry-after: 1000000"). | |||
Clients MUST validate the received values to mitigate those risks. | To mitigate this risk, clients can set thresholds that they consider | |||
reasonable in terms of quota units, time window, concurrent requests | ||||
or throughput, and define a consistent behavior when the RateLimit | ||||
exceed those thresholds. For example this means capping the maximum | ||||
number of request per second, or implementing retries when the reset | ||||
keyword exceeds ten minutes. | ||||
The considerations above are not limited to RateLimit header fields, | ||||
but apply to all fields affecting how clients behave in subsequent | ||||
requests (e.g. Retry-After). | ||||
7. Privacy Considerations | 7. Privacy Considerations | |||
Clients that act upon a request to rate limit are potentially re- | Clients that act upon a request to rate limit are potentially re- | |||
identifiable (see Section 5.2.1 of [PRIVACY]) because they react to | identifiable (see Section 5.2.1 of [PRIVACY]) because they react to | |||
information that might only be given to them. Note that this might | information that might only be given to them. Note that this might | |||
apply to other fields too (e.g. Retry-After). | apply to other fields too (e.g. Retry-After). | |||
Since rate limiting is usually implemented in contexts where clients | Since rate limiting is usually implemented in contexts where clients | |||
are either identified or profiled (e.g. assigning different quota | are either identified or profiled (e.g. assigning different quota | |||
units to different users), this is rarely a concern. | units to different users), this is rarely a concern. | |||
Privacy enhancing infrastructures using RateLimit fields can define | Privacy enhancing infrastructures using RateLimit header fields can | |||
specific techniques to mitigate the risks of re-identification. | define specific techniques to mitigate the risks of re- | |||
identification. | ||||
8. IANA Considerations | 8. IANA Considerations | |||
IANA is requested to update one registry and create one new registry. | IANA is requested to update one registry and create one new registry. | |||
Please add the following entries to the "Hypertext Transfer Protocol | Please add the following entries to the "Hypertext Transfer Protocol | |||
(HTTP) Field Name Registry" registry ([HTTP]): | (HTTP) Field Name Registry" registry ([HTTP]): | |||
+---------------------+-----------+-------------------------+ | +------------------+-----------+-------------------------+ | |||
| Field Name | Status | Specification | | | Field Name | Status | Specification | | |||
+---------------------+-----------+-------------------------+ | +------------------+-----------+-------------------------+ | |||
| RateLimit-Limit | permanent | Section 3.1 of RFC nnnn | | | RateLimit | permanent | Section 3.1 of RFC nnnn | | |||
| RateLimit-Remaining | permanent | Section 3.3 of RFC nnnn | | | RateLimit-Policy | permanent | Section 3.5 of RFC nnnn | | |||
| RateLimit-Reset | permanent | Section 3.4 of RFC nnnn | | +------------------+-----------+-------------------------+ | |||
| RateLimit-Policy | permanent | Section 3.2 of RFC nnnn | | ||||
+---------------------+-----------+-------------------------+ | ||||
8.1. RateLimit Parameters Registration | 8.1. RateLimit Keywords and Parameters Registration | |||
IANA is requested to create a new registry to be called "Hypertext | IANA is requested to create a new registry to be called "Hypertext | |||
Transfer Protocol (HTTP) RateLimit Parameters Registry", to be | Transfer Protocol (HTTP) RateLimit Keywords and Parameters Registry", | |||
located at https://www.iana.org/assignments/http-ratelimit-parameters | to be located at https://www.iana.org/assignments/http-ratelimit- | |||
[1]. Registration is done on the advice of a Designated Expert, | parameters [1]. Registration is done on the advice of a Designated | |||
appointed by the IESG or their delegate. All entries are | Expert, appointed by the IESG or their delegate. All entries are | |||
Specification Required ([IANA], Section 4.6). | Specification Required ([IANA], Section 4.6). | |||
Registration requests consist of the following information: | Registration requests consist of the following information: | |||
o Parameter name: The parameter name, conforming to | o Token name: The keyword or parameter name, conforming to | |||
[STRUCTURED-FIELDS]. | [STRUCTURED-FIELDS]. | |||
o Field name: The RateLimit field for which the parameter is | o Token type: Whether the token is a Dictionary Keyword or a | |||
Parameter Name. | ||||
o Field name: The RateLimit header field for which the parameter is | ||||
registered. If a parameter is intended to be used with multiple | registered. If a parameter is intended to be used with multiple | |||
fields, it has to be registered for each one. | fields, it has to be registered for each one. | |||
o Description: A brief description of the parameter. | o Description: A brief description of the parameter. | |||
o Specification document: A reference to the document that specifies | o Specification document: A reference to the document that specifies | |||
the parameter, preferably including a URI that can be used to | the parameter, preferably including a URI that can be used to | |||
retrieve a copy of the document. | retrieve a copy of the document. | |||
o Comments (optional): Any additional information that can be | o Comments (optional): Any additional information that can be | |||
useful. | useful. | |||
The initial contents of this registry should be: | The initial contents of this registry should be: | |||
+----------------+----------+------------+--------------+-----------+ | +-------------+--------+---------+----------+------------+----------+ | |||
| Field Name | Paramete | Descriptio | Specificatio | Comments | | | Field Name | Token | Token | Descript | Specificat | Comments | | |||
| | r name | n | n | (optional | | | | name | type | ion | ion | (optiona | | |||
| | | | | ) | | | | | | | | l) | | |||
+----------------+----------+------------+--------------+-----------+ | +-------------+--------+---------+----------+------------+----------+ | |||
| RateLimit- | w | Time | Section 2.1 | | | | RateLimit | limit | Diction | Expiring | Section 3. | | | |||
| Policy | | window | of RFC nnnn | | | | | | ary Key | limit | 2 of RFC | | | |||
+----------------+----------+------------+--------------+-----------+ | | | | | | nnnn | | | |||
| RateLimit | remain | Diction | Remainin | Section 3. | | | ||||
| | ing | ary Key | g quota | 3 of RFC | | | ||||
| | | | units | nnnn | | | ||||
| RateLimit | reset | Diction | Quota | Section 3. | | | ||||
| | | ary Key | reset | 4 of RFC | | | ||||
| | | | interval | nnnn | | | ||||
| RateLimit- | w | Paramet | Time | Section 2. | | | ||||
| Policy | | er name | window | 1 of RFC | | | ||||
| | | | | nnnn | | | ||||
+-------------+--------+---------+----------+------------+----------+ | ||||
9. References | 9. References | |||
9.1. Normative References | 9.1. Normative References | |||
[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, | [HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, | |||
Ed., "HTTP Semantics", STD 97, RFC 9110, | Ed., "HTTP Semantics", STD 97, RFC 9110, | |||
DOI 10.17487/RFC9110, June 2022, | DOI 10.17487/RFC9110, June 2022, | |||
<https://www.rfc-editor.org/info/rfc9110>. | <https://www.rfc-editor.org/info/rfc9110>. | |||
skipping to change at line 762 ¶ | skipping to change at page 18, line 10 ¶ | |||
[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>. | |||
[STRUCTURED-FIELDS] | [STRUCTURED-FIELDS] | |||
Nottingham, M. and P-H. Kamp, "Structured Field Values for | Nottingham, M. and P. Kamp, "Structured Field Values for | |||
HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021, | HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021, | |||
<https://www.rfc-editor.org/info/rfc8941>. | <https://www.rfc-editor.org/info/rfc8941>. | |||
[WEB-ORIGIN] | [WEB-ORIGIN] | |||
Barth, A., "The Web Origin Concept", RFC 6454, | Barth, A., "The Web Origin Concept", RFC 6454, | |||
DOI 10.17487/RFC6454, December 2011, | DOI 10.17487/RFC6454, December 2011, | |||
<https://www.rfc-editor.org/info/rfc6454>. | <https://www.rfc-editor.org/info/rfc6454>. | |||
9.2. Informative References | 9.2. Informative References | |||
skipping to change at line 899 ¶ | skipping to change at page 21, line 7 ¶ | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, remaining=0, reset=50 | |||
Ratelimit-Remaining: 0 | ||||
Ratelimit-Reset: 50 | ||||
{"hello": "world"} | {"hello": "world"} | |||
Since the field values are not necessarily correlated with the | Since the field values are not necessarily correlated with the | |||
response status code, a subsequent request is not required to fail. | response status code, a subsequent request is not required to fail. | |||
The example below shows that the server decided to serve the request | The example below shows that the server decided to serve the request | |||
even if RateLimit-Remaining field value is 0. Another server, or the | even if remaining keyword value is 0. Another server, or the same | |||
same server under other load conditions, could have decided to | server under other load conditions, could have decided to throttle | |||
throttle the request instead. | the request instead. | |||
Request: | Request: | |||
GET /items/456 HTTP/1.1 | GET /items/456 HTTP/1.1 | |||
Host: api.example | 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, remaining=0, reset=48 | |||
Ratelimit-Remaining: 0 | ||||
Ratelimit-Reset: 48 | ||||
{"still": "successful"} | {"still": "successful"} | |||
B.1.2. Use in conjunction with custom fields | B.1.2. Use in conjunction with custom fields | |||
The server uses two custom fields, namely "acme-RateLimit-DayLimit" | The server uses two custom fields, namely "acme-RateLimit-DayLimit" | |||
and "acme-RateLimit-HourLimit" to expose the following policy: | and "acme-RateLimit-HourLimit" to expose the following policy: | |||
o 5000 daily quota units; | o 5000 daily quota units; | |||
o 1000 hourly quota units. | o 1000 hourly quota units. | |||
The client consumed 4900 quota units in the first 14 hours. | The client consumed 4900 quota units in the first 14 hours. | |||
Despite the next hourly limit of 1000 quota units, the closest limit | Despite the next hourly limit of 1000 quota units, the closest limit | |||
to reach is the daily one. | to reach is the daily one. | |||
The server then exposes the RateLimit fields to inform the client | The server then exposes the RateLimit header fields to inform the | |||
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 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, remaining=100, reset=36000 | |||
RateLimit-Remaining: 100 | ||||
RateLimit-Reset: 36000 | ||||
{"hello": "world"} | {"hello": "world"} | |||
B.1.3. Use for limiting concurrency | B.1.3. Use for limiting concurrency | |||
Throttling fields may be used to limit concurrency, advertising | RateLimit header fields may be used to limit concurrency, advertising | |||
limits that are lower than the usual ones in case of saturation, thus | limits that are lower than the usual ones in case of saturation, thus | |||
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 field values. | both limit and remaining keyword values. | |||
After 2 seconds the client consumed 40 quota units | After 2 seconds the client consumed 40 quota units | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, remaining=60, reset=58 | |||
RateLimit-Remaining: 60 | ||||
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 "remaining=20". | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, remaining=20, reset=56 | |||
RateLimit-Remaining: 20 | ||||
RateLimit-Reset: 56 | ||||
{"elapsed": 4, "issued": 41} | {"elapsed": 4, "issued": 41} | |||
B.1.4. Use in throttled responses | B.1.4. Use in throttled responses | |||
A client exhausted its quota and the server throttles it sending | A client exhausted its quota and the server throttles it sending | |||
Retry-After. | Retry-After. | |||
In this example, the values of Retry-After and RateLimit-Reset field | In this example, the values of Retry-After and RateLimit header field | |||
reference the same moment, but this is not a requirement. | reference the same moment, but this is not a requirement. | |||
The 429 (Too Many Request) HTTP status code is just used as an | The 429 (Too Many Request) HTTP status code is just used as an | |||
example. | example. | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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: limit=100, remaining=0, reset=5 | |||
RateLimit-Limit: 100 | ||||
Ratelimit-Remaining: 0 | ||||
{ | { | |||
"title": "Too Many Requests", | "title": "Too Many Requests", | |||
"status": 429, | "status": 429, | |||
"detail": "You have exceeded your quota" | "detail": "You have exceeded your quota" | |||
} | } | |||
B.2. Parameterized responses | B.2. Parameterized responses | |||
B.2.1. Throttling window specified via parameter | B.2.1. Throttling window specified via parameter | |||
The client has 99 quota units left for the next 50 seconds. The time | 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 | 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 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, remaining=99, reset=50 | |||
RateLimit-Policy: 100;w=60 | RateLimit-Policy: 100;w=60 | |||
Ratelimit-Remaining: 99 | ||||
Ratelimit-Reset: 50 | ||||
{"hello": "world"} | {"hello": "world"} | |||
B.2.2. Dynamic limits with parameterized windows | B.2.2. Dynamic limits with parameterized windows | |||
The policy conveyed by the RateLimit-Limit field states that the | The policy conveyed by the RateLimit header field states that the | |||
server accepts 100 quota units per minute. | server accepts 100 quota units per minute. | |||
To avoid resource exhaustion, the server artificially lowers the | To avoid resource exhaustion, the server artificially lowers the | |||
actual limits returned in the throttling headers. | actual limits returned in the throttling headers. | |||
The RateLimit-Remaining field then advertises only 9 quota units for | The remaining keyword then advertises only 9 quota units for the next | |||
the next 50 seconds to slow down the client. | 50 seconds to slow down the client. | |||
Note that the server could have lowered even the other values in the | Note that the server could have lowered even the other values in the | |||
RateLimit-Limit field: this specification does not mandate any | RateLimit header field: this specification does not mandate any | |||
relation between the field values contained in subsequent responses. | relation between the field values contained in subsequent responses. | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, remaining=9, reset=50 | |||
RateLimit-Policy: 100;w=60 | RateLimit-Policy: 100;w=60 | |||
Ratelimit-Remaining: 9 | ||||
Ratelimit-Reset: 50 | ||||
{ | { | |||
"status": 200, | "status": 200, | |||
"detail": "Just slow down without waiting." | "detail": "Just slow down without waiting." | |||
} | } | |||
B.2.3. Dynamic limits for pushing back and slowing down | B.2.3. Dynamic limits for pushing back and slowing down | |||
Continuing the previous example, let's say the client waits 10 | Continuing the previous example, let's say the client waits 10 | |||
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 "remaining=0" for the | |||
0" for the next 20 seconds. | 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 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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 | RateLimit: limit=0, remaining=0, reset=20 | |||
RateLimit-Policy: 15;w=20 | RateLimit-Policy: 15;w=20 | |||
Ratelimit-Remaining: 0 | ||||
Ratelimit-Reset: 20 | ||||
{ | { | |||
"status": 429, | "status": 429, | |||
"detail": "Wait 20 seconds, then slow down!" | "detail": "Wait 20 seconds, then slow down!" | |||
} | } | |||
B.3. Dynamic limits for pushing back with Retry-After and slow down | B.3. Dynamic limits for pushing back with Retry-After and slow down | |||
Alternatively, given the same context where the previous example | Alternatively, given the same context where the previous example | |||
starts, we can convey the same information to the client via Retry- | starts, we can convey the same information to the client via Retry- | |||
skipping to change at line 1151 ¶ | skipping to change at page 26, line 17 ¶ | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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 | RateLimit: limit=15, remaining=15, reset=40 | |||
RateLimit-Policy: 100;w=60 | RateLimit-Policy: 100;w=60 | |||
Ratelimit-Remaining: 15 | ||||
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 | Note that in this last response the client is expected to honor | |||
Retry-After and perform no requests for the specified amount of time, | Retry-After and perform no requests for the specified amount of time, | |||
whereas the previous example would not force the client to stop | whereas the previous example would not force the client to stop | |||
requests before the reset time is elapsed, as it would still be free | 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 request | to query again the server even if it is likely to have the request | |||
rejected. | rejected. | |||
B.3.1. Missing Remaining information | B.3.1. Missing Remaining information | |||
The server does not expose RateLimit-Remaining field values (for | The server does not expose remaining keyword values (for example, | |||
example, because the underlying counters are not available). | because the underlying counters are not available). Instead, it | |||
Instead, it resets the limit counter every second. | resets 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 limit and reset keywords. | |||
field. | ||||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, reset=1 | |||
Ratelimit-Reset: 1 | ||||
{"first": "request"} | {"first": "request"} | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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, reset=1 | |||
Ratelimit-Reset: 1 | ||||
{"second": "request"} | {"second": "request"} | |||
B.3.2. Use with multiple windows | B.3.2. Use with multiple windows | |||
This is a standardized way of describing the policy detailed in | This is a standardized way of describing the policy detailed in | |||
Appendix B.1.2: | Appendix B.1.2: | |||
o 5000 daily quota units; | o 5000 daily quota units; | |||
o 1000 hourly quota units. | o 1000 hourly quota units. | |||
The client consumed 4900 quota units in the first 14 hours. | The client consumed 4900 quota units in the first 14 hours. | |||
Despite the next hourly limit of 1000 quota units, the closest limit | Despite the next hourly limit of 1000 quota units, the closest limit | |||
to reach is the daily one. | to reach is the daily one. | |||
The server then exposes the RateLimit fields to inform the client | The server then exposes the RateLimit header fields to inform the | |||
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; | |||
o the expiring-limit is 5000. | o the expiring-limit is 5000. | |||
Request: | Request: | |||
GET /items/123 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
skipping to change at line 1233 ¶ | skipping to change at page 28, line 4 ¶ | |||
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 HTTP/1.1 | GET /items/123 HTTP/1.1 | |||
Host: api.example | 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 | RateLimit: limit=5000, remaining=100, reset=36000 | |||
RateLimit-Policy: 1000;w=3600, 5000;w=86400 | RateLimit-Policy: 1000;w=3600, 5000;w=86400 | |||
RateLimit-Remaining: 100 | ||||
RateLimit-Reset: 36000 | ||||
{"hello": "world"} | {"hello": "world"} | |||
FAQ | FAQ | |||
This section is to be removed before publishing as an RFC. | This section is to be removed before publishing as an RFC. | |||
1. Why defining standard fields for throttling? | 1. Why defining standard fields for throttling? | |||
To simplify enforcement of throttling policies. | To simplify enforcement of throttling policies. | |||
2. Can I use RateLimit fields in throttled responses (eg with status | 2. Can I use RateLimit header fields in throttled responses (eg with | |||
code 429)? | status code 429)? | |||
Yes, you can. | Yes, you can. | |||
3. Are those specs tied to RFC 6585? | 3. Are those specs tied to RFC 6585? | |||
No. [RFC6585] defines the "429" status code and we use it just | No. [RFC6585] defines the "429" status code and we use it just | |||
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. The goal of this specification is | "403" or whatever status code. The goal of this specification is | |||
to standardize the name and semantic of three ratelimit fields | to standardize the name and semantic of three RateLimit header | |||
widely used on the internet. Stricter relations with status | fields widely used on the internet. Stricter relations with | |||
codes or error response payloads would impose behaviors to all | status codes or error response payloads would impose behaviors to | |||
the existing implementations making the adoption more complex. | all the existing implementations making the adoption more | |||
complex. | ||||
4. Why don't pass the throttling scope as a parameter? | 4. Why don't pass the throttling scope as a parameter? | |||
The word "scope" can have different meanings: for example it can | The word "scope" can have different meanings: for example it can | |||
be an URL, or an authorization scope. Since authorization is out | be an URL, or an authorization scope. Since authorization is out | |||
of the scope of this document (see Section 1.1), and that we rely | of the scope of this document (see Section 1.1), and that we rely | |||
only on [HTTP], in Section 1.1 we defined "scope" in terms of | only on [HTTP], in Section 1.1 we defined "scope" in terms of | |||
URL. | URL. | |||
Since clients are not required to process quota policies (see | Since clients are not required to process quota policies (see | |||
skipping to change at line 1315 ¶ | skipping to change at page 29, line 37 ¶ | |||
* 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 [5] | discussion on the subject is on the httpwg ml [5] | |||
* almost all rate-limit headers implementations do not use it. | * almost all rate-limit headers implementations do not use it. | |||
6. Why not support multiple quota remaining? | 6. Why not support multiple quota remaining? | |||
While this might be of some value, my experience suggests that | While this might be of some value, my experience suggests that | |||
overly-complex quota implementations results in lower | overly-complex quota implementations results in lower | |||
effectiveness of this policy. This spec allows the client to | effectiveness of this policy. This spec allows the client to | |||
easily focusing on RateLimit-Remaining and RateLimit-Reset. | easily focusing on the remaining and reset keywords. | |||
7. Shouldn't I limit concurrency instead of request rate? | 7. Shouldn't I limit concurrency instead of request rate? | |||
You can use this specification to limit concurrency at the HTTP | You can use this specification to limit concurrency at the HTTP | |||
level (see {#use-for-limiting-concurrency}) and help clients to | level (see {#use-for-limiting-concurrency}) and help clients to | |||
shape their requests avoiding being throttled out. | shape their requests avoiding being throttled out. | |||
A problematic way to limit concurrency is connection dropping, | A problematic way to limit concurrency is connection dropping, | |||
especially when connections are multiplexed (e.g. HTTP/2) | especially when connections are multiplexed (e.g. HTTP/2) | |||
because this results in unserviced client requests, which is | because this results in unserviced client requests, which is | |||
something we want to avoid. | something we want to avoid. | |||
A semantic way to limit concurrency is to return 503 + Retry- | A semantic way to limit concurrency is to return 503 + Retry- | |||
After in case of resource saturation (e.g. thrashing, connection | After in case of resource saturation (e.g. thrashing, connection | |||
queues too long, Service Level Objectives not meet, ..). | queues too long, Service Level Objectives not meet, ..). | |||
Saturation conditions can be either dynamic or static: all this | Saturation conditions can be either dynamic or static: all this | |||
is out of the scope for the current document. | is out of the scope for the current document. | |||
8. Do a positive value of RateLimit-Remaining field imply any | 8. Do a positive value of remaining keyword imply any service | |||
service guarantee for my future requests to be served? | guarantee for my future requests to be served? | |||
No. FAQ integrated in Section 3.3. | No. FAQ integrated in Section 3.3. | |||
9. Is the quota-policy definition Section 2.1 too complex? | 9. Is the quota-policy definition Section 2.1 too complex? | |||
You can always return the simplest form of the 3 fields | You can always return the simplest form of the 3 fields | |||
RateLimit-Limit: 100 | RateLimit: limit=100, remaining=50, reset=60 | |||
RateLimit-Remaining: 50 | ||||
RateLimit-Reset: 60 | ||||
The key runtime value is the first element of the list: "expiring- | The key runtime value is the first element of the list: "expiring- | |||
limit", the others quota-policy are informative. So for the | limit", the others quota-policy are informative. So for the | |||
following field: | following field: | |||
RateLimit-Limit: 100 | RateLimit: limit=100, remaining=50, reset=44 | |||
RateLimit-Policy: 100;w=60;burst=1000;comment="sliding window", 5000;w=3600;burst=0;comment="fixed window" | RateLimit-Policy: 100;w=60;burst=1000;comment="sliding window", 5000;w=3600;burst=0;comment="fixed window" | |||
the key value is the one referencing the lowest limit: "100" | the key value is the one referencing the lowest limit: "100" | |||
1. Can we use shorter names? Why don't put everything in one field? | 1. Can we use shorter names? Why don't put everything in one field? | |||
The most common syntax we found on the web is "X-RateLimit-*" and | The most common syntax we found on the web is "X-RateLimit-*" and | |||
when starting this I-D we opted for it [6] | when starting this I-D we opted for it [6] | |||
The basic form of those fields is easily parseable, even by | The basic form of those fields is easily parseable, even by | |||
skipping to change at line 1378 ¶ | skipping to change at page 30, line 50 ¶ | |||
1. Why don't mention connections? | 1. Why don't mention connections? | |||
Beware of the term "connection":   - it is just | Beware of the term "connection":   - it is just | |||
_one_ possible saturation cause. Once you go that path  | _one_ possible saturation cause. Once you go that path  | |||
you will expose other infrastructural details (bandwidth, CPU, .. | you will expose other infrastructural details (bandwidth, CPU, .. | |||
see Section 6.2)  and complicate client compliance; | see Section 6.2)  and complicate client compliance; | |||
 - it is an infrastructural detail defined in terms of |  - it is an infrastructural detail defined in terms of | |||
server and network  rather than the consumed service. | server and network  rather than the consumed service. | |||
This specification protects the services first, and then the | This specification protects the services first, and then the | |||
infrastructures through client cooperation (see Section 6.1). | infrastructures through client cooperation (see Section 6.1). | |||
  RateLimit fields enable sending _on the same |   RateLimit header fields enable sending _on the | |||
connection_ different limit values  on each response, | same connection_ different limit values  on each | |||
depending on the policy scope (e.g. per-user, per-custom-key, ..) | response, depending on the policy scope (e.g. per-user, per- | |||
 | custom-key, ..)  | |||
2. Can intermediaries alter RateLimit fields? | 2. Can intermediaries alter RateLimit header 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 header fields though, e.g. when they enforce | |||
quota-policies, or when they are an active component of the | stricter quota-policies, or when they are an active component of | |||
service. In those case we will consider them as part of the | the service. In those case we will consider them as part of the | |||
originating infrastructure. | originating infrastructure. | |||
3. Why the "w" parameter is just informative? Could it be used by a | 3. Why the "w" parameter is just informative? Could it be used by a | |||
client to determine the request rate? | client to determine the request rate? | |||
A non-informative "w" parameter might be fine in an environment | A non-informative "w" parameter might be fine in an environment | |||
where clients and servers are tightly coupled. Conveying | where clients and servers are tightly coupled. Conveying | |||
policies with this detail on a large scale would be very complex | policies with this detail on a large scale would be very complex | |||
and implementations would be likely not interoperable. We thus | and implementations would be likely not interoperable. We thus | |||
decided to leave "w" as an informational parameter and only rely | decided to leave "w" as an informational parameter and only rely | |||
on RateLimit-Limit, RateLimit-Remaining field and RateLimit-Reset | on the limit, remaining and reset keywords for defining the | |||
field for defining the throttling behavior. | throttling behavior. | |||
RateLimit fields currently used on the web | 4. Can I use RateLimit fields in trailers? Servers usually | |||
establish whether the request is in-quota before creating a | ||||
response, so the RateLimit field values should be already | ||||
available in that moment. Supporting trailers has the only | ||||
advantage that allows to provide more up-to-date information to | ||||
the client in case of slow responses. However, this complicates | ||||
client implementations with respect to combining fields from | ||||
headers and accounting for intermediaries that drop trailers. | ||||
Since there are no current implementations that use trailers, we | ||||
decided to leave this as a future-work. | ||||
RateLimit header fields currently used on the web | ||||
This section is to be removed before publishing as an RFC. | This section is to be removed before publishing as an RFC. | |||
Commonly used header field names are: | Commonly used header field names are: | |||
o "X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset"; | o "X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset"; | |||
o "X-Rate-Limit-Limit", "X-Rate-Limit-Remaining", "X-Rate-Limit- | o "X-Rate-Limit-Limit", "X-Rate-Limit-Remaining", "X-Rate-Limit- | |||
Reset". | Reset". | |||
skipping to change at line 1445 ¶ | skipping to change at page 32, line 33 ¶ | |||
o different headers, with the same semantic, are used by different | o different headers, with the same semantic, are used by different | |||
implementers: | implementers: | |||
* X-RateLimit-Limit and X-Rate-Limit-Limit | * X-RateLimit-Limit and X-Rate-Limit-Limit | |||
* X-RateLimit-Remaining and X-Rate-Limit-Remaining | * X-RateLimit-Remaining and X-Rate-Limit-Remaining | |||
* X-RateLimit-Reset and X-Rate-Limit-Reset | * X-RateLimit-Reset and X-Rate-Limit-Reset | |||
The semantic of RateLimit-Remaining depends on the windowing | The semantic of RateLimit depends on the windowing algorithm. A | |||
algorithm. A sliding window policy for example may result in having | sliding window policy for example may result in having a remaining | |||
a RateLimit-Remaining field value related to the ratio between the | keyword value related to the ratio between the current and the | |||
current and the maximum throughput. e.g. | maximum throughput. e.g. | |||
RateLimit-Limit: 12 | RateLimit: limit=12, \ | |||
RateLimit-Policy: 12;w=1 | remaining=6, \ ; using 50% of throughput, that is 6 units/s | |||
RateLimit-Remaining: 6 ; using 50% of throughput, that is 6 units/s | reset=1 | |||
RateLimit-Reset: 1 | RateLimit-Policy: 12;w=1 | |||
If this is the case, the optimal solution is to achieve | If this is the case, the optimal solution is to achieve | |||
RateLimit-Limit: 12 | RateLimit: limit=12, \ | |||
remaining=1 \ ; using 100% of throughput, that is 12 units/s | ||||
reset=1 | ||||
RateLimit-Policy: 12;w=1 | RateLimit-Policy: 12;w=1 | |||
RateLimit-Remaining: 1 ; using 100% of throughput, that is 12 units/s | ||||
RateLimit-Reset: 1 | ||||
At this point you should stop increasing your request rate. | At this point you should stop increasing your request rate. | |||
Acknowledgements | Acknowledgements | |||
Thanks to Willi Schoenborn, Alejandro Martinez Ruiz, Alessandro | Thanks to Willi Schoenborn, Alejandro Martinez Ruiz, Alessandro | |||
Ranellucci, Amos Jeffries, Martin Thomson, Erik Wilde and Mark | Ranellucci, Amos Jeffries, Martin Thomson, Erik Wilde and Mark | |||
Nottingham for being the initial contributors of these | Nottingham for being the initial contributors of these | |||
specifications. Kudos to the first community implementers: Aapo | specifications. Kudos to the first community implementers: Aapo | |||
Talvensaari, Nathan Friedly and Sanyam Dogra. | Talvensaari, Nathan Friedly and Sanyam Dogra. | |||
End of changes. 169 change blocks. | ||||
421 lines changed or deleted | 441 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |