CherryPy Project Download

RateLimitTool

Allows you to apply a rate limit on handlers. Tracks hit counts by either cherry.request.login OR cherry.request.remote.ip. If the rate limit is exceeded the tool will return a 400 http error. Otherwise the request is allowed to continue as normal.

Author: Joshua Roesslein (joshthecoder)

import cherrypy

'''
Example:

rate_limit = RateLimitTool(MyRateInfoStore())

class Root:
  @rate_limit
  def test(self):
    return 'Works!'
'''

class RateLimitTool(cherrypy.Tool):
  def __init__(self, rate_info_store, priority=60):
    self._point = 'on_start_resource'
    self._name = None
    self._priority = priority
    self.__doc__ = self.callable.__doc__
    self._setargs()
    self.rate_info_store = rate_info_store

  def callable(self):
    rate_info = self.rate_info_store.get(cherrypy.request.login, cherrypy.request.remote.ip)
    cherrypy.request.rate_info = rate_info

    if rate_info['hit_count'] > rate_info['limit']:
      raise cherrypy.HTTPError(400) 

  def _record_hit(self):
    if cherrypy.response.status != 500:
      rate_info = cherrypy.request.rate_info
      rate_info['hit_count'] += 1
      self.rate_info_store.put(rate_info)

  def _setup(self):
    '''Hook into cherrypy.request'''
    conf = self._merged_args()
    p = conf.pop('priority', None)
    if p is None:
      p = self._priority
    cherrypy.request.hooks.attach('on_start_resource', self.callable,
                                  priority=p, **conf)
    cherrypy.request.hooks.attach('on_end_request', self._record_hit,
                                  priority=p, **conf)

'''
You must implement this class using your data backend.
'''
class RateInfoStore(object):
  def get(self, login=None, ip_address=None):
    raise NotImplementedError

  def put(self):
    raise NotimplementedError

Hosted by WebFaction

Log in as guest/cherrypy to create/edit wiki pages