def abort(status_code, message=None): """ Raise an exception based on SanicException. Returns the HTTP response message appropriate for the given status code, unless provided. :param status_code: The HTTP status code to return. :param message: The HTTP response body. Defaults to the messages in response.py for the given status code. """ if message is None: message = COMMON_STATUS_CODES.get(status_code, ALL_STATUS_CODES.get(status_code)) # These are stored as bytes in the STATUS_CODES dict message = message.decode('utf8') sanic_exception = _sanic_exceptions.get(status_code, SanicException) raise sanic_exception(message=message, status_code=status_code)
def handle_error(self, request, e): """ Error handler for the API transforms a raised exception into a Sanic response, with the appropriate HTTP status code and body. :param request: The Sanic Request object :type request: sanic.request.Request :param e: the raised Exception object :type e: Exception """ context = restplus.get_context_from_spf(self.spf_reg) app = context.app #got_request_exception.send(app._get_current_object(), exception=e) if not isinstance(e, SanicException) and app.config.get( 'PROPAGATE_EXCEPTIONS', False): exc_type, exc_value, tb = sys.exc_info() if exc_value is e: raise else: raise e include_message_in_response = app.config.get("ERROR_INCLUDE_MESSAGE", True) include_code_in_response = app.config.get("ERROR_INCLUDE_CODE", True) default_data = {} headers = Header() for typecheck, handler in self._own_and_child_error_handlers.items(): if isinstance(e, typecheck): result = handler(e) default_data, code, headers = unpack( result, HTTPStatus.INTERNAL_SERVER_ERROR) break else: if isinstance(e, SanicException): sanic_code = code = e.status_code try: status = e.args[0] assert isinstance(status, (str, bytes)) except (AttributeError, LookupError, AssertionError): if sanic_code is 200: status = b'OK' # x is y comparison only works between -5 and 256 elif sanic_code == 404: status = b'Not Found' elif sanic_code == 500: status = b'Internal Server Error' else: status = ALL_STATUS_CODES.get(int(sanic_code)) code = HTTPStatus(sanic_code, None) if status and isinstance(status, bytes): status = status.decode('ascii') if include_message_in_response: default_data = {'message': getattr(e, 'message', status)} elif self._default_error_handler: result = self._default_error_handler(e) default_data, code, headers = unpack( result, HTTPStatus.INTERNAL_SERVER_ERROR) else: code = HTTPStatus.INTERNAL_SERVER_ERROR status = ALL_STATUS_CODES.get(code.value, str(e)) if status and isinstance(status, bytes): status = status.decode('ascii') if include_message_in_response: default_data = { 'message': status, } if include_message_in_response: default_data['message'] = default_data.get('message', str(e)) if include_code_in_response: default_data['code'] = int(code) data = getattr(e, 'data', default_data) fallback_mediatype = None if code >= HTTPStatus.INTERNAL_SERVER_ERROR: exc_info = sys.exc_info() if exc_info[1] is None or exc_info[0] is None: e_type = e.__class__ e_value = e e_traceback = e.__traceback__ else: e_type, e_value, e_traceback = exc_info context.log(logging.ERROR, "Caught Exception: {}".format(str(e_type))) context.log(logging.ERROR, "Detail: {}".format(str(e_value))) tb = traceback.format_tb(e_traceback) tb = "".join(tb) context.log(logging.ERROR, "Traceback:\n{}".format(tb)) elif code == HTTPStatus.NOT_FOUND and app.config.get("ERROR_404_HELP", False) \ and include_message_in_response: data['message'] = self._help_on_404(request, data.get('message', None)) elif code == HTTPStatus.NOT_ACCEPTABLE and self.default_mediatype is None: # if we are handling NotAcceptable (406), make sure that # make_response uses a representation we support as the # default mediatype (so that make_response doesn't throw # another NotAcceptable error). supported_mediatypes = list(self.representations.keys()) fallback_mediatype = supported_mediatypes[ 0] if supported_mediatypes else "text/plain" # Remove blacklisted headers for header in HEADERS_BLACKLIST: headers.pop(header, None) resp = self.make_response(request, data, code, headers, fallback_mediatype=fallback_mediatype) if code == HTTPStatus.UNAUTHORIZED: resp = self.unauthorized(resp) return resp
def handle_error(self, request, e): ''' Error handler for the API transforms a raised exception into a Flask response, with the appropriate HTTP status code and body. :param Exception e: the raised Exception object ''' # todo: sanic: wtf is this? #got_request_exception.send(current_app._get_current_object(), exception=e) app = request.app headers = CIDict() if e.__class__ in self.error_handlers: handler = self.error_handlers[e.__class__] result = handler(e) default_data, code, headers = unpack(result, 500) elif isinstance(e, SanicException): code = e.status_code status = COMMON_STATUS_CODES.get(code) if not status: status = ALL_STATUS_CODES.get(code) if status and isinstance(status, bytes): status = status.decode('ascii') default_data = {'message': getattr(e, 'message', status)} # headers = e.get_response().headers elif self._default_error_handler: result = self._default_error_handler(e) default_data, code, headers = unpack(result, 500) else: code = 500 status = COMMON_STATUS_CODES.get(code, str(e)) if status and isinstance(status, bytes): status = status.decode('ascii') default_data = { 'message': status, } default_data['message'] = default_data.get('message', str(e)) data = getattr(e, 'data', default_data) fallback_mediatype = None if code >= 500: exc_info = sys.exc_info() if exc_info[1] is None: exc_info = None #current_app.log_exception(exc_info) elif code == 404 and app.config.get("ERROR_404_HELP", True): data['message'] = self._help_on_404(request, data.get('message', None)) elif code == 406 and self.default_mediatype is None: # if we are handling NotAcceptable (406), make sure that # make_response uses a representation we support as the # default mediatype (so that make_response doesn't throw # another NotAcceptable error). supported_mediatypes = list(self.representations.keys()) fallback_mediatype = supported_mediatypes[ 0] if supported_mediatypes else "text/plain" # Remove blacklisted headers for header in HEADERS_BLACKLIST: headers.pop(header, None) resp = self.make_response(request, data, code, headers, fallback_mediatype=fallback_mediatype) if code == 401: resp = self.unauthorized(resp) return resp
def handle_error(self, request, e): ''' Error handler for the API transforms a raised exception into a Flask response, with the appropriate HTTP status code and body. :param Exception e: the raised Exception object ''' context = restplus.get_context_from_spf(self.spf_reg) app = context.app #got_request_exception.send(app._get_current_object(), exception=e) if not isinstance(e, SanicException) and app.propagate_exceptions: exc_type, exc_value, tb = sys.exc_info() if exc_value is e: raise else: raise e include_message_in_response = app.config.get("ERROR_INCLUDE_MESSAGE", True) default_data = {} headers = Header() for typecheck, handler in self._own_and_child_error_handlers.items(): if isinstance(e, typecheck): result = handler(e) default_data, code, headers = unpack( result, HTTPStatus.INTERNAL_SERVER_ERROR) break else: if isinstance(e, SanicException): code = e.status_code if code is 200: status = b'OK' elif code is 404: status = b'Not Found' elif code is 500: status = b'Internal Server Error' else: code = HTTPStatus(code) status = ALL_STATUS_CODES.get(code.value) if status and isinstance(status, bytes): status = status.decode('ascii') if include_message_in_response: default_data = {'message': getattr(e, 'message', status)} elif self._default_error_handler: result = self._default_error_handler(e) default_data, code, headers = unpack( result, HTTPStatus.INTERNAL_SERVER_ERROR) else: code = HTTPStatus.INTERNAL_SERVER_ERROR status = ALL_STATUS_CODES.get(code.value, str(e)) if status and isinstance(status, bytes): status = status.decode('ascii') if include_message_in_response: default_data = { 'message': status, } if include_message_in_response: default_data['message'] = default_data.get('message', str(e)) data = getattr(e, 'data', default_data) fallback_mediatype = None if code >= HTTPStatus.INTERNAL_SERVER_ERROR: exc_info = sys.exc_info() if exc_info[1] is None: exc_info = None context.log(logging.ERROR, exc_info) elif code == HTTPStatus.NOT_FOUND and app.config.get("ERROR_404_HELP", True) \ and include_message_in_response: data['message'] = self._help_on_404(request, data.get('message', None)) elif code == HTTPStatus.NOT_ACCEPTABLE and self.default_mediatype is None: # if we are handling NotAcceptable (406), make sure that # make_response uses a representation we support as the # default mediatype (so that make_response doesn't throw # another NotAcceptable error). supported_mediatypes = list(self.representations.keys()) fallback_mediatype = supported_mediatypes[ 0] if supported_mediatypes else "text/plain" # Remove blacklisted headers for header in HEADERS_BLACKLIST: headers.pop(header, None) resp = self.make_response(request, data, code, headers, fallback_mediatype=fallback_mediatype) if code == HTTPStatus.UNAUTHORIZED: resp = self.unauthorized(resp) return resp