Esempio n. 1
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
Esempio n. 2
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
        headers = CIDict()
        if e.__class__ in self.error_handlers:
            handler = self.error_handlers[e.__class__]
            result = handler(e)
            default_data, code, headers = unpack(
                result, HTTPStatus.INTERNAL_SERVER_ERROR)
        elif 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')
            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, 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')
            default_data = {
                'message': status,
            }

        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):
            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