api/ioutils/request.py

59 lines
1.8 KiB
Python
Raw Normal View History

2024-01-15 13:32:24 +01:00
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