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

Requests that have variable cost? #318

Closed
milescrawford opened this issue Mar 1, 2022 · 12 comments
Closed

Requests that have variable cost? #318

milescrawford opened this issue Mar 1, 2022 · 12 comments

Comments

@milescrawford
Copy link

Hey guys, I'm curious whether flask-limiter could help when requests have variable cost. For instance, can I count a single request against the limit with some multiplier based on the content of the request?

If not, do you all have any thoughts on how to help with this type or metering?

@milescrawford
Copy link
Author

Actually, I see that the underlying API has a cost parameter when recording the hit, and that the limit decorator can adjust this.

This allows for different methods to have different costs, but I still don't see a way to customize the cost based on the request. Is that possible?

@alisaifee
Copy link
Owner

You're right - there's not and this is just an oversight. The api should have been:

def limit(
....
cost: Union[int, Callable[[], int]]

I'll tweak that and make a release soon.

@milescrawford
Copy link
Author

milescrawford commented Mar 6, 2022 via email

@alisaifee
Copy link
Owner

alisaifee commented Mar 6, 2022

The cost callable will be evaluated after the request is complete, correct?

No (in most cases) since the rate limit is evaluated and "hit" in the before request part of the request life cycle (since in most cases you are interested in the protecting the resource you are rate limiting).

Having said that the requirement for conditional actions based on the actual response from the current request has come up often and there are a few ways you can "tweak" the default behaviour.

  1. by using the deduct_when parameter which effectively turns a regular limit which is tested and deducted from in the before request phase, to a limit that is tested in before request (and if the requesting user has already exceeded your resource is protected) and if not the deduction is performed in the after request phase depending on the response from your deduct_when callable. In this scenario the cost callable would be evaluated once in the before request for the test, and once in the after request phase for the deduction.

  2. doing the extra deduction completely manually. As of 2.1 there is a current_limits property available on the extension itself that you can access both during the request and in the after request phase. You could potentially add your own after_request hook and simple do the extra deductions (not great because you'd be making extra requests to your rate limit backend).

I realise both the above suggestions are a bit of a workaround (though perhaps 1 isn't that horrible if you squint a bit 😃 )

Lemme know if the combination of these would work for you ?

@milescrawford
Copy link
Author

milescrawford commented Mar 6, 2022 via email

@milescrawford
Copy link
Author

milescrawford commented Mar 6, 2022 via email

@alisaifee
Copy link
Owner

This is embarrassing, looks like I don't know my way around my own code :D
When using deduct_when the cost function won't be actually called upon in the before_request since to test whether the current request is above the limit or not we don't need the cost, just how much has already been used up. Which means that if you're using deduct_when the cost callable will only be called upon after the request.

@alisaifee
Copy link
Owner

I've pushed a new release 2.2.0 which allows using a function for cost. Should help with the experimentation.

@milescrawford
Copy link
Author

milescrawford commented Mar 6, 2022 via email

@alisaifee
Copy link
Owner

Let me know if this works and if we can close this issue?

@milescrawford
Copy link
Author

milescrawford commented Mar 7, 2022 via email

@milescrawford
Copy link
Author

It works great. I verified that I can access the metadata I need about the request handling from within the cost function when used with deduct_when.

Thank you!

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

2 participants