Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
    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