Replies: 6 comments 6 replies
-
This sounds really great! I have put down some of my questions and thoughts below.
I think you've covered all of the common issues we've had so far (especially the trust proxy one!).
How would we detect this? The (legacy) stores do not provide a function to check and set the
Instead of adding an optional method to the Store API, we could just add a new option to the rate limiter ( The stores themselves could check this by incrementing the hit count, then fetching the count and making sure it is increased by exactly 1. This would definitely have a big impact on performance though. Points 1 and 4 we can implement as you detailed.
Maybe we could use the The checks logger's output can be toggled using the
I think we should keep the
We could make type Options = {
// ...
// which checks to enable
diagnostics: [
'ip-address', // checks that the ip is not undefined, and that it doesn't contain a port number
'trust-proxy', // checks that trust proxy is set properly if the header is present
'store-interface-compliance', // checks that the store function signatures are valid
'store-function-integrity', // checks that increment, decrement and reset actually work
]
} ... now I'm thinking we should keep the first two checks on by default, they seem very useful - especially given the number of issues that have been opened about it.
Could you please give an example as to when this would happen? I can't think of one sorry :O
I think the IP address and trust proxy ones could run every time. They have negligible performance impact, and their input will change every request. The store ones could run only once on launch, and the store can keep track of that using an internal variable. I think this proposal is really brilliant, I look forward to implementing it :D Regards, |
Beta Was this translation helpful? Give feedback.
-
I'm thinking of using either https://www.npmjs.com/package/ip-validator or else just using the regex that it uses (https://www.regextester.com/104038) - the code in the library looks like it recreates the regex each time the function is called.. although I suspect the node.js is smart enough to cache that, so it probably doesn't matter in practice. |
Beta Was this translation helpful? Give feedback.
-
Draft PR up at #358 |
Beta Was this translation helpful? Give feedback.
-
Based on #363, perhaps we should add the link as a separate property on the error object. (In addition to putting it in the message.) |
Beta Was this translation helpful? Give feedback.
-
I also have an idea for how to detect double-counting like what happened in #362. But it's a bit more complex to implement, which is why I skipped it for the initial batch of validations. Basically I want to have a global Also, I need to work out what to do with the MemoryStore and PreciseMemoryStore, since they don't share any state, and than therfore use the same key twice without issue. Maybe And, then, it's unlikely, but the same key being sent to a redis store and a memcached store or whatever also wouldn't cause duplication. Not sure if I really need to handle that case, but I think it may be possible. Maybe |
Beta Was this translation helpful? Give feedback.
-
I think we could detect and warn about situations like #318 by checking for response.headersSent - if it's true then the request was already handled before the ratelimiter ran, and the rate limiter can't do anything! |
Beta Was this translation helpful? Give feedback.
-
I've been thinking about adding a suite of runtime checks to express-rate-limit to detect certain misconfigurations and other potential issues and pro-actively alert users. Some of the checks I've thought of include:
X-Forwarded-For
header is set, buttrust proxy
is not settrust proxy
is set totrue
rather than a number/ip/regex/etc.windowMs
set to a different value than the store's expiration time(These are all based on real issues that have come up. I'm sure that digging through the issues history will reveal a few more.)
I've also been thinking about what response level is appropriate for failed checks - throw an error, log a warning, etc. Some folks will probably want to just disable checks. And some will want different behavior in production than development. (Although, rate-limiting is one of those things that may behave differently in development due to the lack of proxies and/or being disabled entirely.) And then granularity - do we need to allow different response levels for different checks (e.g. allow end-users to disable a specific check but keep all others)? (Also, do I want different defaults for different checks? Should the default change if
process.env.node_env === "production"
?)The last thing on my mind is when to run these checks. Most of them could probably be run once, either at launch or on the first request, and then not need to run again. But I'm not sure if the extra complexity of ensuring the checks only ran on one request is worth it, especially when someone who is worried about the performance could just disable the check entirely.
Beta Was this translation helpful? Give feedback.
All reactions