Hello!
We have the following rate-limit-by-key policy applied on our product group for a simple rate limit.
<policies>
<inbound>
<base />
<rate-limit-by-key calls="30" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization", context.Request.IpAddress))" />
</inbound>
<backend>
<base />
</backend>
<outbound>
</outbound>
<on-error>
<base />
</on-error>
</policies>
The following is a Dummy API that we have to test with policies with the following policies:
<policies>
<inbound>
<base />
<cors>
<allowed-origins>
<origin>*</origin>
</allowed-origins>
<allowed-methods>
<method>GET</method>
<method>POST</method>
<method>PUT</method>
<method>DELETE</method>
<method>PATCH</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
<!-- Determine which key is being used -->
<set-variable name="rateLimitKeyType" value="@(
context.Request.Headers.ContainsKey("Authorization") ? "Authorization" :
context.Request.Headers.ContainsKey("X-Forwarded-For") ? "X-Forwarded-For" :
"IP Address"
)" />
<set-variable name="rateLimitKeyValue" value="@(
context.Request.Headers.GetValueOrDefault("Authorization",
context.Request.Headers.GetValueOrDefault("X-Forwarded-For",
context.Request.IpAddress))
)" />
<!-- Apply rate limit -->
<!--<rate-limit-by-key calls="30" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization",context.Request.Headers.GetValueOrDefault("X-Forwarded-For",context.Request.IpAddress)))" />-->
<!-- <rate-limit-by-key calls="30" renewal-period="60" counter-key="@((string)context.Variables["rateLimitKeyValue"])" /> -->
<return-response>
<set-status code="200" reason="ok" />
<set-header name="Content-Type" exists-action="override">
<value>test</value>
</set-header>
<set-body>@{
return new JObject(
new JProperty("MESSAGE", "succress")
).ToString();
}</set-body>
</return-response>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<!-- Policy to view what key caused the rate-limit to be reached -->
<choose>
<when condition="@(context.Response.StatusCode == 429)">
<return-response>
<set-status code="429" reason="Too Many Requests" />
<set-header name="Content-Type" exists-action="override">
<value>test</value>
</set-header>
<set-body>@{
return new JObject(
new JProperty("error", "Rate limit exceeded (default)"),
new JProperty("limit", "30 requests per 60 seconds"),
new JProperty("keyType", context.Variables["rateLimitKeyType"]),
new JProperty("keyValue", context.Variables["rateLimitKeyValue"]),
new JProperty("Authorization", context.Request.Headers.GetValueOrDefault("Authorization", "missing"))
).ToString();
}</set-body>
</return-response>
</when>
</choose>
<base />
</on-error>
</policies>
The inbound of the API has the <base /> tag, so it should be inheriting the rate-limiting policy. Yet when doing a simple load test the policy is not working. When placing the rate-limit-by-key tag on it's own in the API policy (without the base tag), the rate limiting is working as intended (both in managed and self hosted gateways). What could be the reason that this is the case?
The API is placed in the product group, and the global policies are simple header transformation to mask data, and we are not using workspaces. Has anyone seen anything like this before? The documentation says that rate-limit-by-key is applicable to all scopes.