mirror of
https://github.com/fuckpiracyshield/api.git
synced 2024-12-22 10:40:48 +01:00
58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
from piracyshield_component.log.logger import Logger
|
|
from piracyshield_component.exception import ApplicationException
|
|
|
|
from .response import ResponseHandler
|
|
|
|
import tornado.web
|
|
import time
|
|
|
|
class RequestHandler(ResponseHandler):
|
|
|
|
"""
|
|
Requests gateway.
|
|
"""
|
|
|
|
# override the default methods
|
|
SUPPORTED_METHODS = ("GET", "POST")
|
|
|
|
# max requests allowed in a second
|
|
MAX_REQUESTS_PER_SECOND = 100
|
|
|
|
# requests container
|
|
REQUESTS = {}
|
|
|
|
def prepare(self) -> None:
|
|
"""
|
|
Handles the request general procedures.
|
|
This method implements a very simple request limit check.
|
|
"""
|
|
|
|
self.application.logger.debug(f'> GET `{self.request.uri}` from `{self.request.remote_ip}`')
|
|
|
|
# get the current timestamp in seconds
|
|
timestamp = int(time.time())
|
|
|
|
# TODO: this should be better handled and also provide a way to temporary ban each IP when flooding.
|
|
|
|
# check if the number of requests for this second has exceeded the limit
|
|
if timestamp in self.REQUESTS:
|
|
if self.REQUESTS[timestamp] >= self.MAX_REQUESTS_PER_SECOND:
|
|
self.error(status_code = 429, error_code = ErrorCode.TOO_MANY_REQUESTS, message = ErrorMessage.TOO_MANY_REQUESTS)
|
|
|
|
return
|
|
|
|
# increment the number of requests for this second
|
|
self.REQUESTS[timestamp] = self.REQUESTS.get(timestamp, 0) + 1
|
|
|
|
# decrement the number of requests after one second
|
|
tornado.ioloop.IOLoop.current().call_later(1.0, self._decrement_requests_count, timestamp)
|
|
|
|
def _decrement_requests_count(self, timestamp):
|
|
"""
|
|
Decrement the requests count per timestamp.
|
|
|
|
:param timestamp: current timestamp.
|
|
"""
|
|
|
|
if timestamp in self.REQUESTS:
|
|
self.REQUESTS[timestamp] -= 1
|