envoyproxy / envoyproxy/gateway
`BackendTrafficPolicy`: emit `Retry-After` header on rate-limit 429 responses
- Dominant language
- Go
- Stars
- 3k
- Forks
- 864
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 140
Description
*Description*:
The global rate-limit filter in EG emits the IETF draft-03 triple
(`x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset`) on both
200 and 429 responses, but does not emit `Retry-After` on the 429.
`Retry-After` on 429 is the convention defined by [RFC 6585 section 4](https://www.rfc-editor.org/rfc/rfc6585#section-4),
with the field itself defined by [RFC 9110 section 10.2.3](https://www.rfc-editor.org/rfc/rfc9110#section-10.2.3)
as `HTTP-date / delay-seconds`. Operators today have to bridge this gap
themselves, typically with a Lua filter via `EnvoyExtensionPolicy` that
copies `x-ratelimit-reset` into `Retry-After` on 429. The information is
already in the filter; only the emission is missing.
Proposal: add a option to `BackendTrafficPolicy.spec.rateLimit` (and the
local rate-limit equivalent) that opts the rule or policy into emitting
`Retry-After: ` on rate-limited 429 responses, sourced from
the same reset value the filter already computes. Sketch:
```yaml
spec:
rateLimit:
type: Global
global:
emitRetryAfter: true # or per-rule, mirroring xRateLimitHeaders
rules: [ ... ]
```
The value would be an integer matching the current `x-ratelimit-reset`
semantics: most-restrictive matched rule's seconds-until-reset, clamped
to ≥1. Emission is conditional on the 429, not on every response, to
match RFC 6585 section 4 semantics.
This works for both the RLS-backed global filter and the local rate-limit
filter; the underlying delay value is already computed in both paths.
*Relevant Links*:
- RFC 9110 section 10.2.3, Retry-After: https://www.rfc-editor.org/rfc/rfc9110#section-10.2.3
- RFC 6585 section 4, 429 with Retry-After: https://www.rfc-editor.org/rfc/rfc6585#section-4
- IETF draft-ietf-httpapi-ratelimit-headers (active WG draft, v11): https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/
- Closely related, **closed without delivering Retry-After**:
envoyproxy/gateway#5693, closed after the scope was narrowed to enabling
the existing `x-ratelimit-*` headers on the local rate-limit filter;
the original `Retry-After` ask was not addressed.
- Adjacent CRD surface already shipped in v1.8: envoyproxy/gateway#8279
(`xRateLimitHeaders` per-rule enum), same place the new option would live.
- Upstream Envoy dormant issues for context:
envoyproxy/envoy#12356 (original draft-03 implementation),
envoyproxy/envoy#3555 (custom response headers from the rate-limit
filter/service).
- Envoy `XRateLimitHeadersRFCVersion` enum (frozen at `DRAFT_VERSION_03`):
https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/common/ratelimit/v3/ratelimit.proto
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.