mirror of
https://github.com/fuckpiracyshield/api.git
synced 2024-12-22 18:40:52 +01:00
215 lines
5.2 KiB
Python
215 lines
5.2 KiB
Python
|
import tornado.web
|
||
|
|
||
|
from .errors import ErrorCode, ErrorMessage
|
||
|
|
||
|
import datetime
|
||
|
import json
|
||
|
|
||
|
class ResponseHandler(tornado.web.RequestHandler):
|
||
|
|
||
|
"""
|
||
|
Response handler.
|
||
|
"""
|
||
|
|
||
|
def set_default_headers(self) -> None:
|
||
|
"""
|
||
|
Sets the default headers.
|
||
|
"""
|
||
|
|
||
|
self.set_header('Access-Control-Allow-Origin', '*')
|
||
|
|
||
|
self.set_header('Access-Control-Allow-Methods', 'POST, GET')
|
||
|
|
||
|
self.set_header('Access-Control-Max-Age', 3600)
|
||
|
|
||
|
# response for this API is always a JSON
|
||
|
self.set_header('Content-Type', 'application/json')
|
||
|
|
||
|
# sets the server name
|
||
|
# TODO: let this be configurable
|
||
|
self.set_header('Server', 'piracy-shield')
|
||
|
|
||
|
def set_refresh_cookie(self, value: str) -> None:
|
||
|
"""
|
||
|
Cookie setter.
|
||
|
|
||
|
TODO: need to extend this and have these data loaded from the external config.
|
||
|
|
||
|
:param key: name of the cookie.
|
||
|
:param value: value of the cookie.
|
||
|
"""
|
||
|
|
||
|
self.set_secure_cookie(
|
||
|
name = 'refresh_token',
|
||
|
value = value,
|
||
|
expires_days = 1,
|
||
|
httponly = True,
|
||
|
samesite = "Strict"
|
||
|
# secure = True
|
||
|
)
|
||
|
|
||
|
def get_refresh_cookie(self) -> any:
|
||
|
"""
|
||
|
Handy function to return the refresh token cookie.
|
||
|
"""
|
||
|
|
||
|
return self.get_secure_cookie('refresh_token')
|
||
|
|
||
|
def clear_cookie(self, key: str, **kwargs) -> None:
|
||
|
"""
|
||
|
Cookie remover.
|
||
|
|
||
|
:param key: name of the cookie.
|
||
|
"""
|
||
|
|
||
|
# set to -365 days
|
||
|
expires = -31536000
|
||
|
|
||
|
self.set_cookie(key, value = '', expires = expires, **kwargs)
|
||
|
|
||
|
def success_txt(self, data: str) -> None:
|
||
|
"""
|
||
|
Returns a string in TXT.
|
||
|
|
||
|
:param data: a string to send back as response.
|
||
|
"""
|
||
|
|
||
|
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
|
||
|
|
||
|
self.set_status(200)
|
||
|
|
||
|
self.finish(self.str_to_txt(data))
|
||
|
|
||
|
def success_list_txt(self, data: list) -> None:
|
||
|
"""
|
||
|
Returns a list in TXT.
|
||
|
|
||
|
:param data: a list to send back as response.
|
||
|
"""
|
||
|
|
||
|
self.set_header('Content-Type', 'text/plain; charset=UTF-8')
|
||
|
|
||
|
self.set_status(200)
|
||
|
|
||
|
self.finish(self.list_to_txt(data))
|
||
|
|
||
|
def success(self, data = None, note = None) -> None:
|
||
|
"""
|
||
|
Success response.
|
||
|
|
||
|
:param data: returns data if needed.
|
||
|
"""
|
||
|
|
||
|
self.set_status(200)
|
||
|
|
||
|
response = {
|
||
|
'status': 'success'
|
||
|
}
|
||
|
|
||
|
# this will return empty data as well
|
||
|
response['data'] = data
|
||
|
|
||
|
# generic purpose informations that we want to communicate
|
||
|
if note:
|
||
|
response['note'] = note
|
||
|
|
||
|
self.finish(self.to_json(response))
|
||
|
|
||
|
def error(self, status_code: int, error_code: int, message: str) -> None:
|
||
|
"""
|
||
|
Returns custom format error.
|
||
|
|
||
|
:param status_code: HTTP status code.
|
||
|
:param error_code: custom error code.
|
||
|
:param message: reason of the error.
|
||
|
"""
|
||
|
|
||
|
self.set_status(status_code)
|
||
|
|
||
|
response = {
|
||
|
'status': 'error',
|
||
|
'code': error_code,
|
||
|
'message': message
|
||
|
}
|
||
|
|
||
|
self.application.logger.debug(f'< ERR `{self.request.uri}` {status_code}')
|
||
|
|
||
|
self.finish(self.to_json(response))
|
||
|
|
||
|
# prevent further execution of the code
|
||
|
self._handled = False
|
||
|
|
||
|
# stop execution of the request
|
||
|
self._finished = True
|
||
|
|
||
|
def write_error(self, status_code, **kwargs) -> None:
|
||
|
"""
|
||
|
Override the generic error handler.
|
||
|
|
||
|
:param status_code: HTTP status code.
|
||
|
"""
|
||
|
|
||
|
match status_code:
|
||
|
case 403:
|
||
|
self.error(
|
||
|
status_code = 403,
|
||
|
error_code = ErrorCode.FORBIDDEN,
|
||
|
message = ErrorMessage.FORBIDDEN
|
||
|
)
|
||
|
|
||
|
case 404:
|
||
|
self.error(
|
||
|
status_code = 404,
|
||
|
error_code = ErrorCode.ROUTE_NOT_FOUND,
|
||
|
message = ErrorMessage.ROUTE_NOT_FOUND
|
||
|
)
|
||
|
|
||
|
case 405:
|
||
|
self.error(
|
||
|
status_code = 405,
|
||
|
error_code = ErrorCode.METHOD_NOT_ALLOWED,
|
||
|
message = ErrorMessage.METHOD_NOT_ALLOWED
|
||
|
)
|
||
|
|
||
|
case _:
|
||
|
self.error(
|
||
|
status_code = 400,
|
||
|
error_code = ErrorCode.GENERIC,
|
||
|
message = ErrorMessage.GENERIC
|
||
|
)
|
||
|
|
||
|
def to_json(self, response: dict) -> str:
|
||
|
"""
|
||
|
Converts dictionary into a valid JSON string.
|
||
|
|
||
|
:param response: response data.
|
||
|
"""
|
||
|
|
||
|
return json.dumps(response)
|
||
|
|
||
|
def str_to_txt(self, data: str) -> str:
|
||
|
"""
|
||
|
Converts a list into an UTF-8 string of line by line elements.
|
||
|
|
||
|
:param data: the data to convert.
|
||
|
"""
|
||
|
|
||
|
if data:
|
||
|
return data.encode('utf-8')
|
||
|
|
||
|
return ''
|
||
|
|
||
|
def list_to_txt(self, data: list) -> str:
|
||
|
"""
|
||
|
Converts a list into an UTF-8 string of line by line elements.
|
||
|
|
||
|
:param data: the data to convert.
|
||
|
"""
|
||
|
|
||
|
if data:
|
||
|
converted_data = '\n'.join(data)
|
||
|
|
||
|
return converted_data.encode('utf-8')
|
||
|
|
||
|
return ''
|