def message_received(self, message): """ Called when message from client received. """ multi_response = MultiResponse() try: data = json_decode(message) except ValueError: logger.error('malformed JSON data') yield self.close_sock() raise Return((True, None)) if isinstance(data, dict): # single object request response, err = yield self.process_obj(data) multi_response.add(response) if err: # error occurred, connection must be closed logger.error(err) yield self.sock.send(multi_response.as_message()) yield self.close_sock() raise Return((True, None)) elif isinstance(data, list): # multiple object request if len(data) > self.application.CLIENT_API_MESSAGE_LIMIT: logger.info("client API message limit exceeded") yield self.close_sock() raise Return((True, None)) for obj in data: response, err = yield self.process_obj(obj) multi_response.add(response) if err: # close connection in case of any error logger.error(err) yield self.sock.send(multi_response.as_message()) yield self.send_disconnect_message() yield self.close_sock() raise Return((True, None)) else: logger.error('data not list and not dictionary') yield self.close_sock() raise Return((True, None)) yield self.send(multi_response.as_message()) raise Return((True, None))
def process_api_data(self, project, data): multi_response = MultiResponse() if isinstance(data, dict): # single object request response = yield self.process_api_object(data, project) multi_response.add(response) elif isinstance(data, list): # multiple object request if len(data) > self.ADMIN_API_MESSAGE_LIMIT: raise Return((None, "admin API message limit exceeded (received {0} messages)".format(len(data)))) for obj in data: response = yield self.process_api_object(obj, project) multi_response.add(response) else: raise Return((None, "data not an array or object")) raise Return((multi_response, None))
def process_api_data(self, project, data, is_owner_request): multi_response = MultiResponse() if isinstance(data, dict): # single object request response = yield self.process_api_object(data, project, is_owner_request) multi_response.add(response) elif isinstance(data, list): # multiple object request if len(data) > self.ADMIN_API_MESSAGE_LIMIT: raise Return((None, "admin API message limit exceeded (received {0} messages)".format(len(data)))) for obj in data: response = yield self.process_api_object(obj, project, is_owner_request) multi_response.add(response) else: raise Return((None, "data not an array or object")) raise Return((multi_response, None))
def post(self, project_id): """ Handle API HTTP requests. """ if not self.request.body: raise tornado.web.HTTPError(400, log_message="empty request") if self.request.headers.get("Content-Type", "").startswith("application/json"): # handle JSON requests if corresponding Content-Type specified try: request_data = json_decode(self.request.body) except ValueError: raise tornado.web.HTTPError(400, log_message="malformed json") if not isinstance(request_data, dict): raise tornado.web.HTTPError(400, log_message="object expected") sign = request_data.get("sign") encoded_data = request_data.get("data") else: # handle application/x-www-form-urlencoded request sign = self.get_argument('sign', None) encoded_data = self.get_argument('data', None) if not sign: raise tornado.web.HTTPError(400, log_message="no data sign") if not encoded_data: raise tornado.web.HTTPError(400, log_message="no data") is_owner_request = False if project_id == self.application.OWNER_API_PROJECT_ID: # API request aims to be from superuser is_owner_request = True if is_owner_request: # use api secret key from configuration to check sign secret = self.application.config.get("api_secret") if not secret: raise tornado.web.HTTPError(501, log_message="no api_secret in configuration file") project = None else: project, error = yield self.application.structure.get_project_by_id(project_id) if error: raise tornado.web.HTTPError(500, log_message=str(error)) if not project: raise tornado.web.HTTPError(404, log_message="project not found") # use project secret key to validate sign secret = project['secret_key'] is_valid = auth.check_sign( secret, project_id, encoded_data, sign ) if not is_valid: raise tornado.web.HTTPError(401, log_message="unauthorized") data = auth.decode_data(encoded_data) if not data: raise tornado.web.HTTPError(400, log_message="malformed data") multi_response = MultiResponse() if isinstance(data, dict): # single object request response = yield self.process_object(data, project, is_owner_request) multi_response.add(response) elif isinstance(data, list): # multiple object request if len(data) > self.application.ADMIN_API_MESSAGE_LIMIT: raise tornado.web.HTTPError( 400, log_message="admin API message limit exceeded (received {0} messages)".format( len(data) ) ) for obj in data: response = yield self.process_object(obj, project, is_owner_request) multi_response.add(response) else: raise tornado.web.HTTPError(400, log_message="data not a list or dictionary") if self.application.collector: self.application.collector.incr('api') self.json_response(multi_response.as_message())
def post(self, project_id): """ Handle API HTTP requests. """ if not self.request.body: raise tornado.web.HTTPError(400, log_message="empty request") sign = self.get_argument('sign', None) if not sign: raise tornado.web.HTTPError(400, log_message="no data sign") encoded_data = self.get_argument('data', None) if not encoded_data: raise tornado.web.HTTPError(400, log_message="no data") is_owner_request = False if project_id == self.application.OWNER_API_PROJECT_ID: # API request aims to be from superuser is_owner_request = True if is_owner_request: # use api secret key from configuration to check sign secret = self.application.settings["config"].get("api_secret") if not secret: raise tornado.web.HTTPError( 501, log_message="no api_secret in configuration file") project = None else: project, error = yield self.application.structure.get_project_by_id( project_id) if error: raise tornado.web.HTTPError(500, log_message=str(error)) if not project: raise tornado.web.HTTPError(404, log_message="project not found") # use project secret key to validate sign secret = project['secret_key'] is_valid = auth.check_sign(secret, project_id, encoded_data, sign) if not is_valid: raise tornado.web.HTTPError(401, log_message="unauthorized") data = auth.decode_data(encoded_data) if not data: raise tornado.web.HTTPError(400, log_message="malformed data") multi_response = MultiResponse() if isinstance(data, dict): # single object request response = yield self.process_object(data, project, is_owner_request) multi_response.add(response) elif isinstance(data, list): # multiple object request if len(data) > self.application.ADMIN_API_MESSAGE_LIMIT: raise tornado.web.HTTPError( 400, log_message= "admin API message limit exceeded (received {0} messages)". format(len(data))) for obj in data: response = yield self.process_object(obj, project, is_owner_request) multi_response.add(response) else: raise tornado.web.HTTPError( 400, log_message="data not a list or dictionary") if self.application.collector: self.application.collector.incr('api') self.json_response(multi_response.as_message())