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

Defaults limits do not get applied for other methods when a decorated limit for some methods exists #238

Closed
alisaifee opened this issue Feb 3, 2020 · 3 comments
Assignees
Labels

Comments

@alisaifee
Copy link
Owner

I've simplified the problem into the following script (lim.py) which can be run like so: FLASK_ENV=development FLASK_APP=lim flask run -p 8080 and has the content:

from flask import Blueprint, Flask
from flask_limiter import Limiter
from flask_limiter.util import get_ipaddr as get_remote_address
from flask_restful import Api, Resource


class Config:
    RATELIMIT_DEFAULT = "1/3second"
    RATELIMIT_STORAGE_URL = "redis://"
    RATELIMIT_HEADERS_ENABLED = True
    RATELIMIT_IN_MEMORY_FALLBACK = "1/2second"
    RATELIMIT_KEY_PREFIX = "test-limiter"
    RATELIMIT_SWALLOW_ERRORS = True


app = Flask(__name__)
app.config.from_object(Config)

limiter = Limiter(app, key_func=get_remote_address)

api_bp = Blueprint("api", __name__)
api = Api(api_bp)
app.register_blueprint(api_bp, url_prefix="/api")


class MyResource(Resource):

    decorators = [
       limiter.limit("3/minute", key_func=get_remote_address, methods=["GET"]),
       #limiter.limit("1/3second", key_func=get_remote_address, methods=["POST"])    # this works with your patch if I uncomment
    ]

    def get(self):
        print("GET")
        return {"m": "get"}

    def post(self):
        print("POST")
        return {"m": "post"}


api.add_resource(MyResource, "/my", endpoint="my")

And the requests can be done like so (with httpie):

  • GET: http :8080/api/my
  • POST: http POST :8080/api/my

And as you can see, the "3/minute" GET-only limit (through decorators = [...]) simply exempts my default POST limit, why? If I comment this limit, then my POST (and the rest of the methods work fine, as expected) and if I try to explicitly set another default limit for POST method ("1/3second" like seen in the 2nd commented limit) by just have uncommented both limits, the POST limit is still exempted with the current library, but given your patch, this problem is solved if-and-only-if we make that workaround for re-specifying then again an explicit limit for the rest of the methods (like POST).

Wouldn't be nice to not be obliged to explicitly specify default limits for unaffected methods? (like POSTs in my scenario)
When I say methods=["GET"] doesn't this mean that I want only GETs given that resource being affected?
Secondly: I had previously a 1/3second limit for any type of request (applied over the GET too). When I specify a new limit (like in decorators = [...] under the resource), aren't we expecting to have that decorator put on top of the default one (having both 1/3second default limit + 3/minute for GETs only)? Or at least have an override=True flag under .limit() so if I switch this to False I'll have this limit compounded to the other already available/set ones. But this is a finer problem; would be nice to fix at least the one above: when specifying a GET-only limit to not lose the POST one (and be forced to make the workaround of specifying one for the POST too just because we wanted a custom one for GET under the same resource).

I think this example is much more clearer now, please let me know if you're still perplexed.

Originally posted by @cmin764 in #11 (comment)

@alisaifee
Copy link
Owner Author

Thanks @cmin764 for helping me understand the issue. It's perfectly clear now and is definitely a bug.

The main issue right now is that if any decorated limit exists on a view default limits are ignored completely. The correct implementation would be if any decorated limit exists and is valid in the request context, the defaults should be ignored.

Having said that your issue shows theres a potential need for more flexibility with:

  1. Allowing defaults to be always applied in combination with overrides
  2. Having the ability to specify that default limits are per-method (since in your case the get request would have its own limit and put,post etc (if you had those methods) would all share one limit)

I'll address the above two separately.

@alisaifee alisaifee self-assigned this Feb 3, 2020
@alisaifee alisaifee added the bug label Feb 3, 2020
@alisaifee
Copy link
Owner Author

@cmin764 when you get the chance, could you please try out the fix in the b-238-default-limits branch?

@cmin764
Copy link

cmin764 commented Feb 9, 2020

b-238-default-limits

Yep, just tested it out and works like a charm! Thank you.

Now would be nice if we can decide through a flag called override=True in the .limit() method an overriding behavior for the newly applied limit. If the default value of True is set as False, then the newly applied limit should be stacked on top of the others, otherwise have applied just this one.

Currently it is not that clear or obvious to lose a default limit when explicitly decorating with others. The initial tendency is to think they are stacked by default.

L.E.: Please let me know when you make the release into PyPI too, so I can adapt my project accordingly. Thank you for committing into this matter!

netbsd-srcmastr referenced this issue in NetBSD/pkgsrc Nov 5, 2023
v3.5.0
------
Release Date: 2023-08-30

* Feature

  * Add `meta_limits` to allow for creating upper limits for
    requesting clients to breach application rate limits.

* Bug fix

  * Ensure on breach callbacks can be configured using flask config

v3.4.1
------
Release Date: 2023-08-26

* Bug fix

  - Ensure _version.py has stable content when generated
    using `git archive` from a tag regardless of when it is
    run.

v3.4.0
------
Release Date: 2023-08-22

* Feature

  * Add extended configuration for application limits

    * `application_limits_exempt_when`
    * `application_limits_deduct_when`
    * `application_limits_per_method`

* Bug fix

  * Ensure blueprint static routes are exempt

v3.3.1
------
Release Date: 2023-05-03

* Chores

  * Improve default limits documentation
  * Update documentation dependencies
  * Fix typing compatibility errors in headers

v3.3.0
------
Release Date: 2023-02-26

* Bug Fix

  * Ensure per route limits are preferred (over application limits)
    when populating rate limiting headers in the case where no rate limit has been
    breached in the request.

v3.2.0
------
Release Date: 2023-02-15

* Feature

  * Allow configuring request identity

* Chores

  * Improve linting with ruff
  * Update development dependencies


v3.1.0
------
Release Date: 2022-12-29

* Feature

  * Skip logging an error if a decorated limit uses a callable
    to return the "current" rate limit and returns an empty string.
    Treat this is a signal that the rate limit should be skipped for
    this request.

v3.0.0
------
Release Date: 2022-12-28

* Breaking changes

  * Change order of extension constructor arguments to only require
    ``key_func`` as the first positional argument and all other arguments
    as keyword arguments.
  * Separate positional/keyword arguments in limit/shared_limit decorators
  * Remove deprecated config variable RATELIMIT_STORAGE_URL
  * Remove legacy backward compatibility path for flask < 2

* Features

  * Allow scoping regular limit decorators / context managers

v3.0.0b2
--------
Release Date: 2022-12-28

* Breaking changes

  * Remove deprecated config variable RATELIMIT_STORAGE_URL
  * Remove legacy backward compatibility path for flask < 2
  * Enforce key_func as a required argument

* Chores

  * Simplify registration of decorated function & blueprint limits

v3.0.0b1
--------
Release Date: 2022-12-26

* Breaking changes

  * Change order of extension constructor arguments to only require
    ``key_func`` as the first positional argument and all other arguments
    as keyword arguments.
  * Separate positional/keyword arguments in limit/shared_limit decorators

* Features

  * Allow scoping regular limit decorators / context managers

v2.9.2
------
Release Date: 2022-12-26

* Feature

  * Extend customization by http method to shared_limit decorator

v2.9.1
------
Release Date: 2022-12-26

* Chores

  * Update documentation quick start
  * Refresh documentation for class based views

v2.9.0
------
Release Date: 2022-12-24

* Features

  * Allow using `limit` & `shared_limit` decorators on pure
    functions that are not decorated as routes. The functions
    when called from within a request context will get rate limited.
  * Allow using `limit` as a context manager to rate limit a code block
    explicitly within a request

* Chores

  * Updated development dependencies
  * Fix error running tests depending on docker locally
  * Update internals to use dataclasses

v2.8.1
------
Release Date: 2022-11-15

* Chores

  * Add sponsorship banner to rtd
  * Update documentation dependencies

v2.8.0
------
Release Date: 2022-11-13

* Breaking changes

  * Any exception raised when calling an ``on_breach`` callback will
    be re-raised instead of being absorbed unless ``swallow_errors`` is set.
    In the case of ``swallow_errors`` the exception will now be logged
    at ``ERROR`` level instead of ``WARN``
  * Reduce log level of rate limit exceeded log messages to ``INFO``

v2.7.0
------
Release Date: 2022-10-25

* Bug Fix

  * Add default value for RateLimitExceeded optional parameter
  * Fix suppression of errors when using conditional deduction (`Issue 363 <https://github.com/alisaifee/flask-limiter/issues/363>`_)

v2.6.3
------
Release Date: 2022-09-22

* Compatibility

  * Ensure typing_extensions dependency has a minimum version

* Chores

  * Documentation tweaks
  * Update CI to use 3.11 rc2

v2.6.2
------
Release Date: 2022-08-24

* Chores

  * Improve quick start documentation

v2.6.1
------
Release Date: 2022-08-23

* Usability

  * Emit warning when in memory storage is used as a default
    when no storage uri is provided

v2.6.0
------
Release Date: 2022-08-11

* Feature

  * Expand use of ``on_breach`` callback to return a ``Response``
    object that will be used as the error response on rate limits
    being exceeded


v2.5.1
------
Release Date: 2022-08-05

* Compatibility

  * Migrate use of `flask._request_ctx_stack` to `flask.globals.request_ctx`
    to support Flask 2.2+

* Chores

  * Expand CI matrix to test against Flask 2.0,2.1 & 2.2
  * Make tests compatible with Flask 2.2.+

v2.5.0
------
Release Date: 2022-07-07

* Features

  * Ensure multiple extension instances registered
    on a single application exercise before/after request
    hooks

* Chores

  * Improve documentation

v2.4.6
------
Release Date: 2022-06-06

* Chore

  * Add python 3.11 to CI matrix


v2.4.5.1
--------
Release Date: 2022-04-22

* Chore

  * Automate github releases

v2.4.5
------
Release Date: 2022-04-21

* Chore

  * Automate github releases

v2.4.4
------
Release Date: 2022-04-21

* Chore

  * Automate github releases

v2.4.3
------
Release Date: 2022-04-21

* Chore

  * Second attempt to generate release notes

v2.4.2
------
Release Date: 2022-04-21

* Chore

  * Test for automating github release notes

v2.4.1
------
Release Date: 2022-04-21

* Chore

  * Automate github releases

v2.4.0
------
Release Date: 2022-04-20

* Feature

  * Add CLI for inspecting & clearing rate limits

* Bug Fix

  * Ensure exempt decorator can be used with flags for view functions

* Chores

  * Refactor rate limit resolution to limit manager

v2.3.3
------
Release Date: 2022-04-20

* Bug Fix

  * Ensure `request.blueprint` is actually registered on the current app before
    using it for blueprint limits or exemptions. (`Issue 336 <https://github.com/alisaifee/flask-limiter/issues/336>`_)

v2.3.2
------
Release Date: 2022-04-17

* Feature

  * Extend cost parameter to default & application limits

* Chore

  * Improve type strictness / checking
  * Improve documentation on landing page

v2.3.1
------
Release Date: 2022-04-14

* Bug Fixes

  * Add missing extras requirements for installation
  * Add py.typed for PEP 561 compliance

v2.3.0
------
Release Date: 2022-04-11

* Features

  * Expose option to register a callback for rate limit breaches
    of default limits via the :paramref:`~flask_limiter.Limiter.on_breach`
    constructor parameter
  * Replace use of `flask.g` with request context for keeping track of
    extension state (:issue:`327`)
  * Rework implementation of :meth:`~flask_limiter.Limiter.exempt` to accomodate
    nested blueprints. (:issue:`326`)

* Chores

  * Add python 3.11 to CI
  * Extract management and filtering of limits to LimitManager
  * Improve correctness of resolving inherited limits & extensions
    when working with Blueprints (especially nested ones)


v2.2.0
------
Release Date: 2022-03-05

* Feature

  * Allow a function to be used for the ``cost`` parameter
    to limiter decorators.

v2.1.3
------
Release Date: 2022-01-30

* Chore

  * Update documentation theme

v2.1
----
Release Date: 2022-01-15

* Feature

  * Add ``current_limit`` attribute to extension to
    allow clients to fetch the relevant current limit
    that was evaluated.
  * Update extension constructor parameters to match
    flask config for header control
  * Add ``on_breach`` callback for ``limit`` and ``shared_limit``
    decorators to be used as hooks for when a limit is breached
  * Add ``cost`` argument to ``limit`` and ``shared_limit`` to control
    how much is deducted when a hit occurs.

* Chore

  * Improve documentation around configuration

* Deprecation

  * Remove hacks for managing incorrectly ordered
    limit/route decorators

v2.0.4
------
Release Date: 2021-12-22

* Chore

  * Documentation theme upgrades
  * Integrate pytest-docker plugin
  * Mass linting

* Deprecation

  * Removed deprecated RATELIMIT_GLOBAL config
  * Added deprecation doc for RATELIMIT_STORAGE_URL config

v2.0.3
------
Release Date: 2021-12-15

Documentation & test tweaks

v2.0.2
------
Release Date: 2021-11-28

* Features

  * Pin Flask, limits to >= 2
  * Add type hints

v2.0.1
------
Release Date: 2021-11-28

* Deprecations

  * Remove deprecated get_ipaddr method
  * Remove use of six
  * Remove backward compatibility hacks for RateLimit exceptions

v2.0.0
------
Release Date: 2021-11-27

Drop support for python < 3.7 & Flask < 2.0

v1.5
----
Release Date: 2021-11-27

Final Release for python < 3.7

* Features

  * Prepend ``key_prefix`` to extension variables attached to ``g``
  * Expose ``g.view_limits``

v1.4
----
Release Date: 2020-08-25

* Bug Fix

  * Always set headers for conditional limits
  * Skip init_app sequence when the rate limiter is disabled

v1.3.1
------
Release Date: 2020-05-21

* Bug Fix

  * Ensure headers provided explictely by setting `_header_mapping`
    take precedence over configuration values.

v1.3
----
Release Date: 2020-05-20

* Features

  * Add new ``deduct_when`` argument that accepts a function to decorated limits
    to conditionally perform depletion of a rate limit (`Pull Request 248 <https://github.com/alisaifee/flask-limiter/pull/248>`_)
  * Add new ``default_limits_deduct_when`` argument to Limiter constructor to
    conditionally perform depletion of default rate limits
  * Add ``default_limits_exempt_when`` argument that accepts a function to
    allow skipping the default limits in the ``before_request`` phase

* Bug Fix

  * Fix handling of storage failures during ``after_request`` phase.

* Code Quality

  * Use github-actions instead of travis for CI
  * Use pytest instaad of nosetests
  * Add docker configuration for test dependencies
  * Increase code coverage to 100%
  * Ensure pyflake8 compliance


v1.2.1
------
Release Date: 2020-02-26

* Bug fix

  * Syntax error in version 1.2.0 when application limits are provided through
    configuration file (`Issue 241 <https://github.com/alisaifee/flask-limiter/issues/241>`_)

v1.2.0
------
Release Date: 2020-02-25

* Add `override_defaults` argument to decorated limits to allow combinined defaults with decorated limits.
* Add configuration parameter RATELIMIT_DEFAULTS_PER_METHOD to control whether defaults are applied per method.
* Add support for in memory fallback without override (`Pull Request 236 <https://github.com/alisaifee/flask-limiter/pull/236>`_)
* Bug fix

  * Ensure defaults are enforced when decorated limits are skipped (`Issue 238 <https://github.com/alisaifee/flask-limiter/issues/238>`_)

v1.1.0
------
Release Date: 2019-10-02

* Provide Rate limit information with Exception (`Pull Request 202 <https://github.com/alisaifee/flask-limiter/pull/202>`_)
* Respect existing Retry-After header values (`Pull Request 143 <https://github.com/alisaifee/flask-limiter/pull/143>`_)
* Documentation improvements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants