fix(rate-limit): answer with the JSON error shape rather than plain text - #244
Merged
Conversation
Closes #241. Every other 4xx and 5xx on this API is { error }. A 429 was the exception: express-rate-limit sends a string message through res.send, which lands as text/html, so a client parsing error bodies as JSON got a parse failure. Grepping for the string found three of the nine sites. The other six set no message at all and inherited the library's own string default, so they were plain text for the same reason without saying so. All nine now send an object. The message on the slow-down is removed rather than converted. express-slow-down replaces the handler with one that only delays and calls next, so it never answers a request and that option could never be read. Two consumers were already coping with the text form: @seamless-auth/core has a makeJsonTolerant shim in authFetch that names this case, and seamless-auth-react was crashed by it once. The admin dashboard maps 429 to fixed wording and never surfaces upstream text.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #241.
Nine sites, not three
The issue named the three limiters that set
message: 'Too many requests, please try again later'. The other six set no message at all and inherited express-rate-limit's own string default, so they answered plain text for the same reason without saying so anywhere. Grep found a third of the problem.Verified against the library rather than assumed:
message429 text/htmlToo many requests, please try again later.429 text/htmlToo many requests, please try again later429 application/json{"error":"..."}All nine, including the JWKS limiter, now send the object and answer
{ "error": "Too many requests, please try again later" }.The slow-down message was unreachable
slowDown.tsalso carried the string. express-slow-down replaces the handler with one that only computes a delay and callsnext, so it never answers a request and that option could never be read. Removed rather than converted, since converting dead config to different dead config is worse than deleting it.Contract change and blast radius
The
429body and content type change. Surveyed before committing, and both known consumers were coping with the text form rather than depending on it:@seamless-auth/core:authFetch.tscarries amakeJsonTolerantshim whose comment names this exact case. Every adapter response passes through it because of this one endpoint.seamless-auth-react: seamless-auth-react#41, a non-JSON 429 crashing the client.seamless-auth-admin-dashboard: maps429to fixed wording and never surfaces upstream text. Unaffected.Nothing depended on the text, so no coordinated release is needed. Whether
makeJsonTolerantcan now be simplified is being looked at separately; it also covers204, so it is not a straight deletion.Tests
Verification
1216 tests passing, 1 skipped. Typecheck, lint, format clean.
minorchangeset per the pre-1.0 rule, describing the behaviour change.docs/api-contract.mdupdated: it claimed every4xxand5xxused one shape, which was not quite true until now.