Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditional rate limiting. #2758

Open
ponimas opened this issue Nov 29, 2023 · 1 comment
Open

Conditional rate limiting. #2758

ponimas opened this issue Nov 29, 2023 · 1 comment

Comments

@ponimas
Copy link
Member

ponimas commented Nov 29, 2023

Is your feature request related to a problem? Please describe.
We want to be able to apply clusterClientRatelimit based on existence or absence of certain headers in the incoming requests, so we can put several filters in one route and expect that only ratelimits with matching conditions are applied.
At the moment, achieving this requires the use of separate routes, each with its own rate limiter, which is extremely hard to support.

*
-> customFilterSettingHeaderXHeaderInCaseOfConditions()
-> setRequestHeader("loopedBack", "true")
-> <loopback>;

Header("loopedBack", "true") &&
Header("X-Header", ".+")
-> clusterClientRatelimit("A", 30, "10s", "X-Header,X-AnotherHeader")
-> "http://192.3.123.1:909";

Header("loopedBack", "true") &&
-> clusterClientRatelimit("B", 10, "100s", "X-AnotherHeader,X-True-Ip")
-> "http://192.3.123.1:909";

What would we like to have

*
-> customFilterSettingHeaderXHeaderInCaseOfConditions()
-> clusterClientRatelimit("A", 30, "10s", "(X-Header exists in the request),X-AnotherHeader")
-> clusterClientRatelimit("B", 10, "100s", "(X-Header doesn't exist in the request),X-AnotherHeader,X-True-Ip")
-> "http://192.3.123.1:909

Describe the solution you would like
A Rejected PR with an example solution.

Describe alternatives you've considered (optional)
A clear and concise description of any alternative solutions or features you've considered.

Additional context (optional)
Add any other context or screenshots about the feature request here.

Would you like to work on it?
Yes, but no time

@AlexanderYastrebov
Copy link
Member

I was looking at Common Expression Language (CEL) recently also used by Kubernetes for various rules.

We may think about a new filter that would set header value based on the result of CEL expression and then use it in the clusterClientRatelimit (which applies rate limit when header is not empty) like so:

*
-> customFilterSettingHeaderXHeaderInCaseOfConditions()

-> setRequestHeaderExpr("Ratelimit-A", `request.Header["X-Header"] != "" ? request.Header["X-AnotherHeader"] : null`)
-> clusterClientRatelimit("A", 30, "10s", "Ratelimit-A")

-> setRequestHeaderExpr("Ratelimit-B", `request.Header["X-Header"] == "" ? request.Header["X-AnotherHeader"] + request.Header["X-True-Ip"] : null`)
-> clusterClientRatelimit("B", 10, "100s", "Ratelimit-B")

-> "http://192.3.123.1:909"

For brevity we may put Header (and other request fields) directly into CEL environment (i.e. omit request. prefix) and use shorter expressions like Header["X-Header"] && URL.Path == "/foo" && URL.Query.Has("q") ? "/foo" + Header["X-AnotherHeader"] : null

I also investigated whether it is possible to wire stdlib http.Request and other types into CEL and it seems possible, see google/cel-go#875

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants