def put(self, tip_token, *uriargs): """ Request: actorsTipOpsDesc Response: None Errors: InvalidTipAuthToken, InvalidInputFormat, ForbiddenOperation This interface modify some tip status value. pertinence, personal delete are handled here. Total delete operation is handled in this class, by the DELETE HTTP method. Those operations (may) trigger a 'system comment' inside of the Tip comment list. This interface return None, because may execute a delete operation. The client know which kind of operation has been requested. If a pertinence vote, would perform a refresh on get() API, if a delete, would bring the user in other places. """ try: # Until whistleblowers has not right to perform Tip operations... if not is_receiver_token(tip_token): raise ForbiddenOperation request = validateMessage(self.request.body, requests.actorsTipOpsDesc) answer = yield CrudOperations().update_tip_by_receiver(tip_token, request) self.set_status(answer['code']) except (InvalidInputFormat, ForbiddenOperation, TipGusNotFound, TipPertinenceExpressed) as error: self.write_error(error) self.finish()
def post(self, *uriargs): """ Request: wbSubmissionDesc Response: wbSubmissionDesc Errors: ContextGusNotFound, InvalidInputFormat, SubmissionFailFields This creates an empty submission for the requested context, and returns submissionStatus with empty fields and a Submission Unique String, This is the unique token used during the submission procedure. sessionGUS is used as authentication secret for the next interaction. expire after the time set by Admin (Context dependent setting) """ try: request = validateMessage(self.request.body, requests.wbSubmissionDesc) answer = yield CrudOperations().new_submission(request) # TODO - output processing self.set_status(answer["code"]) self.write(answer["data"]) except ContextGusNotFound, e: self.set_status(e.http_status) self.write({"error_message": e.error_message, "error_code": e.error_code})
def put(self, receiver_token_auth, *uriargs): """ Parameters: receiver_token_auth Request: receiverReceiverDesc Response: receiverReceiverDesc Errors: ReceiverGusNotFound, InvalidInputFormat, InvalidTipAuthToken, TipGusNotFound """ receivertip_iface = ReceiverTip() try: request = validateMessage(self.request.body, requests.receiverReceiverDesc) receivers_map = yield receivertip_iface.get_receivers_by_tip(receiver_token_auth) # receivers_map is a dict with these keys: 'others' : [$], 'actor': $, 'mapped' [ ] self_receiver_gus = receivers_map['actor']['receiver_gus'] receiver_iface = Receiver() receiver_desc = yield receiver_iface.self_update(self_receiver_gus, request) # context_iface = Context() # yield context_iface.update_languages() -- TODO review in update languages and tags self.write(receiver_desc) self.set_status(200) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, tip_token, *uriargs): """ Request: actorsCommentDesc Response: actorsCommentDesc Errors: InvalidTipAuthToken, InvalidInputFormat, TipGusNotFound, TipReceiptNotFound """ comment_iface = Comment() try: request = validateMessage(self.request.body, requests.actorsCommentDesc) if is_receiver_token(tip_token): requested_t = ReceiverTip() tip_description = yield requested_t.get_single(tip_token) comment_stored = yield comment_iface.add_comment(tip_description['internaltip_id'], request['content'], u"receiver", tip_description['receiver_gus']) else: requested_t = WhistleblowerTip() tip_description = yield requested_t.get_single(tip_token) comment_stored = yield comment_iface.add_comment(tip_description['internaltip_id'], request['content'], u"whistleblower") self.set_status(200) self.write(json.dumps(comment_stored)) except TipGusNotFound, e: self.set_status(e.http_status) self.write({'error_message' : e.error_message, 'error_code' : e.error_code})
def put(self, receiver_gus, *uriargs): """ Request: adminReceiverDesc Response: adminReceiverDesc Errors: InvalidInputFormat, ReceiverGusNotFound, ContextGus Update information about a Receiver, return the instance updated. """ try: # TODO parameter validation - InvalidInputFormat request = validateMessage(self.request.body, requests.adminReceiverDesc) receiver_iface = Receiver() yield receiver_iface.update(receiver_gus, request) # 'contexts' it's a relationship between two tables, and is managed # with a separate method of new() context_iface = Context() yield receiver_iface.receiver_align(receiver_gus, request['contexts']) yield context_iface.full_context_align(receiver_gus, request['contexts']) receiver_description = yield receiver_iface.get_single(receiver_gus) self.set_status(200) self.write(receiver_description) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: adminReceiverDesc Response: adminReceiverDesc Errors: InvalidInputFormat, ContextGusNotFound Create a new receiver """ try: request = validateMessage(self.request.body, requests.adminReceiverDesc) receiver_iface = Receiver() new_receiver = yield receiver_iface.new(request) new_receiver_gus = new_receiver['receiver_gus'] # 'contexts' it's a relationship between two tables, and is managed # with a separate method of new() context_iface = Context() yield receiver_iface.receiver_align(new_receiver_gus, request['contexts']) yield context_iface.full_context_align(new_receiver_gus, request['contexts']) new_receiver_desc = yield receiver_iface.get_single(new_receiver_gus) self.set_status(201) # Created self.write(new_receiver_desc) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, context_gus, *uriargs): """ Request: adminContextDesc Response: adminContextDesc Errors: InvalidInputFormat, ContextGusNotFound, ReceiverGusNotFound """ try: request = validateMessage(self.request.body, requests.adminContextDesc) context_iface = context.Context() yield context_iface.update(context_gus, request) if request['receivers']: receiver_iface = receiver.Receiver() yield context_iface.context_align(context_gus, request['receivers']) yield receiver_iface.full_receiver_align(context_gus, request['receivers']) context_description = yield context_iface.admin_get_single(context_gus) self.set_status(200) self.write(context_description) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: adminReceiverDesc Response: adminReceiverDesc Errors: InvalidInputFormat, ContextGusNotFound Create a new receiver """ try: request = validateMessage(self.request.body, requests.adminReceiverDesc) receiver_iface = receiver.Receiver() new_receiver_gus = yield receiver_iface.new(request) if request['contexts']: context_iface = context.Context() yield receiver_iface.receiver_align(new_receiver_gus, request['contexts']) yield context_iface.full_context_align(new_receiver_gus, request['contexts']) new_receiver_desc = yield receiver_iface.admin_get_single(new_receiver_gus) self.set_status(201) # Created self.write(new_receiver_desc) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, tip_token, *uriargs): """ Request: actorsTipOpsDesc Response: actorsTipDesc Errors: InvalidTipAuthToken, InvalidInputFormat, ForbiddenOperation This interface modify some tip status value. pertinence, personal delete are handled here. Total delete operation is handled in this class, by the DELETE HTTP method. Those operations (may) trigger a 'system comment' inside of the Tip comment list. """ try: request = validateMessage(self.request.body, requests.actorsTipOpsDesc) if not is_receiver_token(tip_token): raise ForbiddenOperation requested_t = ReceiverTip() if request['personal_delete']: yield requested_t.personal_delete(tip_token) if request['is_pertinent']: yield requested_t.pertinence_vote(tip_token, request['is_pertinent']) self.set_status(200) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message' : e.error_message, 'error_code' : e.error_code})
def put(self, receiver_token_auth, conf_id, *uriargs): """ Parameters: Parameters: receiver_token_auth, receiver_configuration_id Request: receiverConfDesc Response: receiverConfDesc Errors: InvalidInputFormat, ProfileGusNotFound, ContextGusNotFound, ReceiverGusNotFound, update the resource ReceiverConf by a specific receiver, and if is requested as active, deactivate the others related to the same context. """ try: request = validateMessage(self.request.body, requests.receiverReceiverDesc) auth_user = yield AuthOperations().authenticate_receiver(receiver_token_auth) answer = yield CrudOperations().update_receiversetting(auth_user['receiver_gus'], conf_id, request, auth_user) self.write(answer['data']) self.set_status(answer['code']) except InvalidTipAuthToken, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, receiver_gus, *uriargs): """ Request: adminReceiverDesc Response: adminReceiverDesc Errors: InvalidInputFormat, ReceiverGusNotFound, ContextGus Update information about a Receiver, return the instance updated. """ try: # TODO parameter validation - InvalidInputFormat request = validateMessage(self.request.body, requests.adminReceiverDesc) receiver_iface = receiver.Receiver() yield receiver_iface.admin_update(receiver_gus, request) if request['contexts']: context_iface = context.Context() yield receiver_iface.receiver_align(receiver_gus, request['contexts']) yield context_iface.full_context_align(receiver_gus, request['contexts']) receiver_description = yield receiver_iface.admin_get_single(receiver_gus) self.set_status(200) self.write(receiver_description) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, context_gus, *uriargs): """ Request: adminContextDesc Response: adminContextDesc Errors: InvalidInputFormat, ContextGusNotFound, ReceiverGusNotFound """ try: request = validateMessage(self.request.body, requests.adminContextDesc) context_iface = Context() yield context_iface.update(context_gus, request) # 'receivers' it's a relationship between two tables, and is managed # with a separate method of new() receiver_iface = Receiver() yield context_iface.context_align(context_gus, request['receivers']) yield receiver_iface.full_receiver_align(context_gus, request['receivers']) context_description = yield context_iface.get_single(context_gus) self.set_status(200) self.write(context_description) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: wbSubmissionDesc Response: wbSubmissionDesc Errors: ContextGusNotFound, InvalidInputFormat, SubmissionFailFields This creates an empty submission for the requested context, and returns submissionStatus with empty fields and a Submission Unique String, This is the unique token used during the submission procedure. sessionGUS is used as authentication secret for the next interaction. expire after the time set by Admin (Context dependent setting) """ context_iface = Context() try: request = validateMessage(self.request.body, requests.wbSubmissionDesc) # XXX DUMMY PATCH CLIENT USAGE -- open tiket in GLClient print "Before", request if not request.has_key('wb_fields'): request.update({'wb_fields' : ''}) if not request.has_key('receivers'): request.update({'receivers' : []}) if not request.has_key('files'): request.update({'files' : []}) if not request.has_key('finalize'): request.update({'finalize' : False }) print "After ", request # XXX DUMMY PATCH CLIENT USAGE -- open tiket in GLClient context_desc = yield context_iface.get_single(request['context_gus']) submission_iface = Submission() submission_desc = yield submission_iface.new(request) if not context_desc['selectable_receiver']: submission_iface.receivers = context_iface.receivers if submission_desc['finalize']: internaltip_iface = InternalTip() wb_iface = WhistleblowerTip() internaltip_desc = yield internaltip_iface.new(submission_desc) wbtip_desc = yield wb_iface.new(internaltip_desc) submission_desc.update({'receipt' : wbtip_desc['receipt']}) else: submission_desc.update({'receipt' : ''}) self.set_status(201) # Created # TODO - output processing self.write(submission_desc) except ContextGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def prepare(self): """ This method is called by cyclone, and is implemented to handle the POST fallback, in environment where PUT and DELETE method may not be used. """ if config.debug.verbose: print "Just got %s" % self.request.body if self.request.method.lower() == "post": try: wrappedMethod = self.get_argument("method")[0] print "[^] Forwarding", wrappedMethod, "from POST" if wrappedMethod.lower() == "delete" or wrappedMethod.lower() == "put": self.request.method = wrappedMethod.upper() except HTTPError: pass if self.request.method in self.requestTypes: validMessage = self.requestTypes[self.request.method] validateMessage(self.request.body, validMessage)
def put(self, receiver_token_auth, conf_id, *uriargs): """ Parameters: Parameters: receiver_token_auth, receiver_configuration_id Request: receiverConfDesc Response: receiverConfDesc Errors: InvalidInputFormat, ProfileGusNotFound, ContextGusNotFound, ReceiverGusNotFound, update the resource ReceiverConf by a specific receiver, and if is requested as active, deactivate the others related to the same context. """ receivertip_iface = ReceiverTip() try: request = validateMessage(self.request.body, requests.receiverReceiverDesc) receivers_map = yield receivertip_iface.get_receivers_by_tip(receiver_token_auth) user = receivers_map['actor'] # ++ sanity checks that can't be make by validateMessage or by model: profile_iface = PluginProfiles() profile_desc = yield profile_iface.get_single(request['profile_gus']) if profile_desc['plugin_type'] == u'notification' and user['can_configure_notification']: pass elif profile_desc['plugin_type'] == u'delivery' and user['can_configure_delivery']: pass else: raise ForbiddenOperation # -- end of the sanity checks receivercfg_iface = ReceiverConfs() config_update = yield receivercfg_iface.update(conf_id, user['receiver_gus'], request) if config_update['active']: # keeping active only the last configuration requested yield receivercfg_iface.deactivate_all_but(config_update['config_id'], config_update['context_gus'], user['receiver_gus'], config_update['plugin_type']) self.write(config_update) self.set_status(200) # OK except InvalidTipAuthToken, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, receiver_token_auth, *uriargs): """ Parameters: receiver_token_auth Request: receiverConfDesc Response: receiverConfDesc Errors: TipGusNotFound, InvalidTipAuthToken, ForbiddenOperation, ContextGusNotFound, ReceiverGusNotFound Create a new configuration for a plugin """ receivertip_iface = ReceiverTip() try: request = validateMessage(self.request.body, requests.receiverReceiverDesc) receivers_map = yield receivertip_iface.get_receivers_by_tip(receiver_token_auth) user = receivers_map['actor'] # ++ sanity checks that can't be make by validateMessage or by model: profile_iface = PluginProfiles() profile_desc = yield profile_iface.get_single(request['profile_gus']) if profile_desc['plugin_type'] == u'notification' and user['can_configure_notification']: pass elif profile_desc['plugin_type'] == u'delivery' and user['can_configure_delivery']: pass else: raise ForbiddenOperation # -- end of the sanity checks receivercfg_iface = ReceiverConfs() config_desc = yield receivercfg_iface.new(user['receiver_gus'], request) if config_desc['active']: # keeping active only the last configuration requested yield receivercfg_iface.deactivate_all_but(config_desc['config_id'], config_desc['context_gus'], user['receiver_gus'], config_desc['plugin_type']) self.write(config_desc) self.set_status(201) # Created except InvalidTipAuthToken, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, conf_id, receiver_gus, *uriargs): """ Parameters: receiver_gus, receiver_configuration_id Response: receiverConfDesc Errors: InvalidInputFormat, ReceiverConfNotFound, ReceiverGusNotFound """ try: request = validateMessage(self.request.body, requests.receiverReceiverDesc) answer = yield CrudOperations().update_receiversetting(receiver_gus, conf_id, request) self.write(answer['data']) self.set_status(answer['code']) except ReceiverGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: adminContextDesc Response: adminContextDesc Errors: InvalidInputFormat, ReceiverGusNotFound """ try: request = validateMessage(self.request.body, requests.adminContextDesc) answer = yield CrudOperations().create_context(request) # validateMessage() output!! self.write(answer['data']) self.set_status(answer['code']) except (InvalidInputFormat, ContextGusNotFound) as error: self.write_error(error) self.finish()
def post(self, *uriargs): """ Request: adminContextDesc Response: adminContextDesc Errors: InvalidInputFormat, ReceiverGusNotFound """ try: request = validateMessage(self.request.body, requests.adminContextDesc) answer = yield CrudOperations().create_context(request) # validateMessage() output!! self.write(answer['data']) self.set_status(answer['code']) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: wbSubmissionDesc Response: wbSubmissionDesc Errors: ContextGusNotFound, InvalidInputFormat, SubmissionFailFields This creates an empty submission for the requested context, and returns submissionStatus with empty fields and a Submission Unique String, This is the unique token used during the submission procedure. sessionGUS is used as authentication secret for the next interaction. expire after the time set by Admin (Context dependent setting) """ try: request = validateMessage(self.request.body, requests.wbSubmissionDesc) submission = Submission() context_iface = Context() context_info = context_iface.public_get_single(request['context_gus']) # use requested context, for defaults and so on status = yield submission.new(request['context_gus']) submission_gus = status['submission_gus'] # submission.receivers = context_iface. if request.has_key('fields'): log.debug("Fields present in creation: %s" % request['fields']) yield submission.update_fields(submission_gus, request['fields']) # TODO check if context supports receiver_selection if request.has_key('receivers'): yield submission.select_receiver(submission_gus, request['receivers']) self.set_status(201) # Created # TODO - output processing self.write(status) except ContextGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, submission_gus, *uriargs): """ Parameter: submission_gus Request: wbSubmissionDesc Response: wbSubmissionDesc Errors: ContextGusNotFound, InvalidInputFormat, SubmissionFailFields, SubmissionGusNotFound, SubmissionConcluded PUT update the submission and finalize if requested. """ context_iface = Context() try: request = validateMessage(self.request.body, requests.wbSubmissionDesc) context_desc = yield context_iface.get_single(request['context_gus']) submission_iface = Submission() submission_desc = yield submission_iface.update(submission_gus, request) if not context_desc['selectable_receiver']: submission_iface.receivers = context_iface.receivers if submission_desc['finalize']: internaltip_iface = InternalTip() wb_iface = WhistleblowerTip() internaltip_desc = yield internaltip_iface.new(submission_desc) wbtip_desc = yield wb_iface.new(internaltip_desc) submission_desc.update({'receipt' : wbtip_desc['receipt']}) else: submission_desc.update({'receipt' : ''}) self.set_status(202) # Updated # TODO - output processing self.write(submission_desc) except ContextGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def delete(self, submission_gus, *uriargs): """ Parameter: submission_gus Request: wbSubmissionDesc Response: None Errors: SubmissionGusNotFound, InvalidInputFormat A whistleblower is deleting a Submission because has understand that won't really be an hero. :P """ try: request = validateMessage(self.request.body, requests.wbSubmissionDesc) submission = Submission() submission.submission_delete(request.submission_gus) except SubmissionGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, tip_token, *uriargs): """ Request: actorsTipOpsDesc Response: None Errors: InvalidTipAuthToken, InvalidInputFormat, ForbiddenOperation This interface modify some tip status value. pertinence, personal delete are handled here. Total delete operation is handled in this class, by the DELETE HTTP method. Those operations (may) trigger a 'system comment' inside of the Tip comment list. This interface return None, because may execute a delete operation. The client know which kind of operation has been requested. If a pertinence vote, would perform a refresh on get() API, if a delete, would bring the user in other places. """ try: request = validateMessage(self.request.body, requests.actorsTipOpsDesc) if not is_receiver_token(tip_token): raise ForbiddenOperation receivertip_iface = ReceiverTip() if request['personal_delete']: yield receivertip_iface.personal_delete(tip_token) elif request['is_pertinent']: # elif is used to avoid the message with both delete+pertinence. # This operation is based in ReceiverTip and is returned # the sum of the vote expressed. This value is updated in InternalTip (itip_id, vote_sum) = yield receivertip_iface.pertinence_vote(tip_token, request['is_pertinent']) internaltip_iface = InternalTip() yield internaltip_iface.update_pertinence(itip_id, vote_sum) self.set_status(200) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message' : e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: adminProfileDesc Response: adminProfileDesc Errors: InvalidInputFormat, ProfileNameConflict """ try: # TODO input mesage validation, or InvalidInputFormat request = validateMessage(self.request.body, requests.adminProfileDesc) answer = yield CrudOperations().create_profile(request) # validateMessage() output!! self.write(answer['data']) self.set_status(answer['code']) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, profile_gus, *uriargs): """ Parameters: profile_gus Request: adminProfileDesc Response: adminProfileDesc Errors: ProfileGusNotFound, InvalidInputFormat, ProfileNameConflict """ try: # validateParameter(profile_gus, requests.profileGUS) request = validateMessage(self.request.body, requests.adminProfileDesc) answer = yield CrudOperations().update_profile(profile_gus, request) # validateMessage() output!! self.write(answer['data']) self.set_status(answer['code']) except ProfileGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, *uriargs): """ Request: adminProfileDesc Response: adminProfileDesc Errors: InvalidInputFormat, ProfileNameConflict """ try: # TODO input mesage validation, or InvalidInputFormat request = validateMessage(self.request.body, requests.adminProfileDesc) profile_iface = PluginProfiles() profile_description = yield profile_iface.new(request) self.set_status(200) self.write(profile_description) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def post(self, tip_token, *uriargs): """ Request: actorsCommentDesc Response: actorsCommentDesc Errors: InvalidTipAuthToken, InvalidInputFormat, TipGusNotFound, TipReceiptNotFound """ try: request = validateMessage(self.request.body, requests.actorsCommentDesc) if is_receiver_token(tip_token): answer = yield CrudOperations().new_comment_by_receiver(tip_token, request) else: answer = yield CrudOperations().new_comment_by_wb(tip_token, request) self.write(answer['data']) self.set_status(answer['code']) except (TipGusNotFound, TipReceiptNotFound) as error: self.write_error(error) self.finish()
def put(self, *uriargs): """ Request: adminNodeDesc Response: adminNodeDesc Errors: InvalidInputFormat Changes the node public node configuration settings """ try: request = validateMessage(self.request.body, requests.adminNodeDesc) answer = yield CrudOperations().update_node(request) # validateMessage() output!! self.write(answer['data']) self.set_status(answer['code']) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, receiver_token_auth, *uriargs): """ Parameters: receiver_token_auth Request: receiverReceiverDesc Response: receiverReceiverDesc Errors: ReceiverGusNotFound, InvalidInputFormat, InvalidTipAuthToken, TipGusNotFound """ try: request = validateMessage(self.request.body, requests.receiverReceiverDesc) auth_user = yield AuthOperations().authenticate_receiver(receiver_token_auth) answer = yield CrudOperations().update_receiver_by_receiver(auth_user['receiver_gus'], request) self.write(answer['data']) self.set_status(answer['code']) except InvalidInputFormat, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def put(self, *uriargs): """ Request: adminNodeDesc Response: adminNodeDesc Errors: InvalidInputFormat Changes the node public node configuration settings """ try: request = validateMessage(self.request.body, requests.adminNodeDesc) answer = yield CrudOperations().update_node(request) # validateMessage() output!! self.write(answer['data']) self.set_status(answer['code']) except (InvalidInputFormat) as error: self.write_error(error) self.finish()