Skip to content

fix(cors): expose Retry-After so browser JS can honor 429 back-off (#322)#323

Merged
CryptoJones merged 1 commit into
masterfrom
fix/cors-expose-retry-after
May 19, 2026
Merged

fix(cors): expose Retry-After so browser JS can honor 429 back-off (#322)#323
CryptoJones merged 1 commit into
masterfrom
fix/cors-expose-retry-after

Conversation

@CryptoJones
Copy link
Copy Markdown
Owner

Closes #322.

Summary

Adds 'Retry-After' to server.js exposedHeaders and mirrors the entry in the CORS expose-headers test. Adds an assertion in the rate-limit test that the 429 response actually carries the header (positive-integer-seconds per RFC 7231 §7.1.3).

Without this, browser JS reading a cross-origin 429 sees Retry-After as null and can't honor the server's back-off.

Test plan

  • npm run lint && npm test — 782 passing (1 new assertion added to existing 429 test rather than a new test block).

Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/

express-rate-limit (standardHeaders: true) sets `Retry-After` on
the 429 response — the integer-seconds the client should wait
before retrying (RFC 7231 §7.1.3). Browser JS reading the
response across CORS can't see headers outside the CORS-safelisted
set unless the server explicitly exposes them via
`Access-Control-Expose-Headers`.

`Retry-After` is NOT on the CORS safelist (only Cache-Control,
Content-Language, Content-Length, Content-Type, Expires,
Last-Modified, Pragma are), so a browser-side `fetch()` getting
a 429 reads `headers.get('Retry-After')` as null and falls back
to a fixed-delay retry instead of honoring the server's
back-off. Add it to the existing exposedHeaders list alongside
the other RateLimit-* headers.

Update tests:
  - cors-expose-headers.test.js mirrors the new entry.
  - rate-limit.test.js asserts the 429 response actually carries
    `Retry-After` as a positive-integer string (defensive — the
    server-side path could change without the CORS list catching
    it).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@CryptoJones CryptoJones merged commit 9a45159 into master May 19, 2026
3 checks passed
@CryptoJones CryptoJones deleted the fix/cors-expose-retry-after branch May 19, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CORS: Retry-After header not exposed, browser JS can't honor 429 back-off

1 participant