I'm trying to apply policies at two levels and am not clear on how to achieve my goal. I'd like to:
At the product level:
- Rate limit 60 calls per minute
- Forbid certain IPs from calling
At a a specific operation level (let's call it operationWithRatePolicyPlusBase
):
- Use the base policy's IP filtering rule
- Apply a more strict rate limiting policy of 10 call per minute
I've applied this at the product level:
<inbound>
<base />
<rate-limit-by-key calls="60" renewal-period="60" counter-key="@(context.Request.IpAddress)" />
<ip-filter action="forbid">
...
</ip-filter>
</inbound>
and at the operation level:
<inbound>
<rate-limit-by-key calls="10" renewal-period="60" counter-key="@(context.Request.IpAddress)" />
<base />
</inbound>
What I'm seeing is that calling a different operation operationWithOnlyBasePolicy
(ie - one that the product scope would apply to, but not the operation scope) seems to count toward the rate limiting on operationWithRatePolicyPlusBase
. For example:
- Call
operationWithOnlyBasePolicy
10 times in parallel - Call
operationWithRatePolicyPlusBase
a single time
Actual Behavior - the call to operationWithRatePolicyPlusBase
is immediately rate limited and returns 429
after calling only one time.
Expected behavior - the call to operationWithRatePolicyPlusBase
is not limited until the rate limit policy at the operation level is met (ie 10 calls in less than a minute).
I can work around this by either removing the base for operationWithRatePolicyPlusBase
and duplicating it at the operation or by using a custom key that includes the operation name at the operation level rate limiting policy, like this:
<rate-limit-by-key calls="10" renewal-period="60" counter-key="@(context.Request.IpAddress context.Request.OriginalUrl.Path.ToString().ToLower())" />
Both seem hacky and I can't make sense of the behavior I'm seeing. Is there a better way to achieve the goal of having rate limiting apply to both the product and a more strict version at the operation level?
CodePudding user response:
The Counter Key is global and shared between all the scopes, operations, Apis and products so if you use it at more than one place, then yes, you may get throttled earlier than what you expect as with every policy hit, the counter will increase. The workaround you used, is not hacky, it is the right way of doing it but instead, use the operation Id, product Id or the API Id to have distinguished and unique keys.