В моем приложении Tornado есть два класса.
Первый класс - это BaseRequestHandler, который расширяет tornado.web.RequestHandler и переопределяет его метод prepare() для проверки API-ключа всех входящих запросов.
Второй - это класс ChildRequestHandler, специфичный для маршрута, который расширяет BaseRequestHandler.
ChildRequestHandler также имеет метод prepare(), который выполняет некоторую проверку параметров, но перед этим вызывает метод prepare() для BaseRequestHandler.
Теперь метод prepare() обоих классов вызывает методы finish() для tornado.web.RequestHandler, если проверка не выполняется.
Ниже приведены примеры обоих классов.
Базовый класс
class BaseRequestHandler(RequestHandler):
# Override Write Error method
def write_error(self, status_code, chunk):
self.set_status(status_code)
self.finish({'message': chunk})
# Prepare method to validate API Key
def prepare(self):
# Send Unauthorized error
if 'X-API-KEY' not in self.request.headers:
self.write_error(401, 'API Key {X-API-KEY} Required')
return None
# Set API Key from header
self.apikey = self.request.headers['X-API-KEY']
Дочерний класс
class ChildRequestHandler(BaseRequestHandler):
# Check for required parameters
def prepare(self):
# Call Prepare of base class
super(ChildRequestHandler, self).prepare()
username = self.get_query_argument('username', None)
if username is None:
self.write_error(400, 'Username {username} Required')
Проблема возникает при сбое проверки в базовом классе. Затем он выдает ошибку времени выполнения finish() called twice, поскольку метод prepare() дочернего класса также выполняется независимо от результата проверки базового класса.
Это можно решить, вернув логическое значение из метода prepare() базового класса, чтобы определить, прошла ли проверка, и затем соответственно разрешить выполнение метода prepare() дочернего класса.
Но есть ли что-нибудь вроде self.finished(), чтобы определить, завершен ли запрос? Я проверил документацию и не нашел такого метода.






Нет общедоступного метода finished() (хотя нет причин, по которым его нельзя было бы добавить). Я рекомендую создать подкласс tornado.web.HTTPError вместо прямого вызова write_error, чтобы prepare() не возвращался нормально после возникновения ошибки.
Ах да ... Как я мог это пропустить !! Спасибо. Теперь я поднимаю
HTTPErrorи также переопределяю методwrite_errorдля отправки ответаapplication/json.