예제 #1
0
    def initialize(self, application_settings, handler=None):  # pylint: disable=arguments-differ
        self.application_settings = application_settings
        self.handler = handler
        self.request_id = self.request.headers.get(
            constants.REQUEST_ID_HTTP_HEADER)

        config.dictConfig(settings.LOGGING)
        logger = getLogger(settings.LOGGER_NAME)

        environment_name = 'MFS_ENV'

        environment = os.environ.get(environment_name)
        if not environment:
            raise exceptions.GeneralInfoException(
                '{0} environment variable not found'.format(environment_name))
        self.environment = environment

        session_info = {
            'environment': environment,
            'service': self.settings.get('service_name'),
            'handler': handler,
            'requestId': self.request_id
        }
        self.support = Support(logger, session_info)

        self.resource_name = "{0}_{1}".format(session_info['service'],
                                              handler if handler else '')
예제 #2
0
    def initialize(self, application_settings, handler=None):  # pylint: disable=arguments-differ
        self.application_settings = application_settings
        self.handler = handler
        self.request_id = self.request.headers.get(constants.REQUEST_ID_HTTP_HEADER)

        config.dictConfig(settings.LOGGING)
        logger = getLogger(settings.LOGGER_NAME)

        environment_name = 'MFS_ENV'

        environment = os.environ.get(environment_name)
        if not environment:
            raise exceptions.GeneralInfoException(
                '{0} environment variable not found'.format(environment_name))
        self.environment = environment

        session_info = {
            'environment': environment,
            'service': self.settings.get('service_name'),
            'handler': handler,
            'requestId': self.request_id
        }
        self.support = Support(logger, session_info)

        self.resource_name = "{0}_{1}".format(session_info['service'],
                                              handler if handler else '')
예제 #3
0
class BaseHandler(web.RequestHandler):  # pylint: disable=too-many-public-methods
    """
    BaseHandler
    """
    def __init__(self, application, request, **kwargs):
        """
        Constructor
        """
        super(BaseHandler, self).__init__(application, request, **kwargs)
        self.context = None

    def data_received(self, chunk):
        pass

    def initialize(self, application_settings, handler=None):  # pylint: disable=arguments-differ
        self.application_settings = application_settings
        self.handler = handler
        self.request_id = self.request.headers.get(constants.REQUEST_ID_HTTP_HEADER)

        config.dictConfig(settings.LOGGING)
        logger = getLogger(settings.LOGGER_NAME)

        environment_name = 'MFS_ENV'

        environment = os.environ.get(environment_name)
        if not environment:
            raise exceptions.GeneralInfoException(
                '{0} environment variable not found'.format(environment_name))
        self.environment = environment

        session_info = {
            'environment': environment,
            'service': self.settings.get('service_name'),
            'handler': handler,
            'requestId': self.request_id
        }
        self.support = Support(logger, session_info)

        self.resource_name = "{0}_{1}".format(session_info['service'],
                                              handler if handler else '')

    def prepare(self):
        """
        Called at the beginning of a request before get/post/etc.
        Override this method to perform common initialization regardless of the
        request method
        """

        try:
            self.process_query()
            self.process_headers()
            self.process_body()

            request = self.request

            self.support.notify_debug(
                "[BaseHandler] request: %s %s" % (str(request.method), str(request.uri)))
            self.support.notify_debug(
                "[BaseHandler] query: %s" % str(request.query))
            self.support.notify_debug(
                "[BaseHandler] headers: %s" % str(request.headers))
            self.support.notify_debug(
                "[BaseHandler] body: %s" % str(request.body))

            body_size = sys.getsizeof(request.body)
            self.support.stat_increment('net.requests.total_count')
            self.support.stat_increment('net.requests.total_bytes', body_size)
            self.support.stat_increment('net.requests.' + str(request.method) + '_count')
            self.support.stat_increment('net.requests.' + str(request.method) + '_bytes', body_size)

        except exceptions.InfoException as ex:
            self.support.notify_error(ex)
            self.build_response(ex)
        except Exception as ex:  # pylint: disable=W0703
            self.support.notify_error(ex)
            self.build_response(ex)

    def set_default_headers(self):
        self.set_header("Server", "Miramar Web Server")
        self.set_header('Access-Control-Allow-Headers', 'Authorization, '
                        + 'Content-Type, ' + constants.REQUEST_ID_HTTP_HEADER)
        self.set_header('Access-Control-Allow-Credentials', 'true')
        self.set_header('Access-Control-Allow-Origin', '*')
        self.set_header('Access-Control-Max-Age', '1728000')

    def process_headers(self, required_headers=None):
        """
        Process the request headers to validate if the headers in required_headers
        come in the request.
        Overwrite this method to extend this behavior or to change it at all.
        """

        if required_headers is None:
            required_headers = []
        else:
            pass

        if (self.request.method == 'POST') or (self.request.method == 'PUT'):
            required_headers.append('Content-Type')
        else:
            pass

        missing_headers = []
        for header in required_headers:
            if self.request.headers.get(header) is None:
                missing_headers.append(header)
            else:
                pass

        if len(missing_headers):
            raise exceptions.MissingArgumentValue('these headers are required: %s' %
                                                  missing_headers)
        else:
            pass

    def process_query(self, supported_query_attributes=None):
        """
        Process the request query.
        Overwrite this method to extend this behavior or to change it at all.
        """
        if supported_query_attributes:
            processed_query = self.request.arguments
            unsupported_attributes = list(
                set(processed_query.keys()) - set(supported_query_attributes))
            if unsupported_attributes:
                raise exceptions.InvalidArgument(
                    'The following query parameters are not supported: %s' %
                    unsupported_attributes)

    def process_body(self):
        """
        Process the request body to validate if it is valid based on the
        Content-Type header.
        Overwrite this method to extend this behavior or to change it at all.
        """

        body = self.request.body
        method = self.request.method

        if method == 'POST' or method == 'PUT':
            content_type = self.request.headers.get('Content-Type')

            if content_type.startswith('application/json'):
                try:
                    processed_body = json.loads(
                        body, object_pairs_hook=collections.OrderedDict)
                except (TypeError, ValueError) as ex:
                    raise exceptions.InvalidArgument('invalid body: %s' % ex)
            else:
                processed_body = self.request.arguments
        else:
            processed_body = None

        self.request.body_arguments = processed_body

    def build_response(self, result, status_code=None):
        """
        Build the response data with the required format according to result
        """
        self._build_response_internal(True, result, status_code)

    def build_response_without_format(self, result, status_code=None):
        """
        Build the response data with the required format according to result
        """
        self._build_response_internal(False, result, status_code)

    def _build_response_internal(self, apply_format, result, status_code=None):
        """
        Build the response data with the required format according to result
        """

        if apply_format:
            self.set_header("Content-Type", "application/json")

        if isinstance(result, Exception):
            body = self._build_response_from_exception(result)
            self.write(body)
        else:
            if apply_format:
                body = json.dumps(result)
            else:
                body = result

            if self.request.method == 'GET':
                self.set_status(status_code if status_code is not None else 200)
                self.write(body)
            elif self.request.method == 'POST':
                self.set_status(status_code if status_code is not None else 201)
                self.write(body)
            elif self.request.method == 'PUT':
                self.set_status(status_code if status_code is not None else 204)
            elif self.request.method == 'DELETE':
                self.set_status(status_code if status_code is not None else 200)
            else:
                pass

        if self.request_id:
            self.set_header(constants.REQUEST_ID_HTTP_HEADER, self.request_id)

        self.support.stat_increment('net.responses.total_count')
        self.support.stat_increment('net.responses.total_bytes', sys.getsizeof(body))

        self.finish()

    def _build_response_from_exception(self, ex):
        """
        Build HTTP response from an exception
        """
        if isinstance(ex, exceptions.BadRequestBase):
            self.set_status(400)
            response_body = str(ex)
        elif isinstance(ex, exceptions.UnauthorizedBase):
            self.set_status(401)
            response_body = str(ex)
        elif isinstance(ex, exceptions.ForbiddenBase):
            self.set_status(403)
            response_body = str(ex)
        elif isinstance(ex, exceptions.NotFoundBase):
            self.set_status(404)
            response_body = str(ex)
        elif isinstance(ex, exceptions.PermanentServiceError):
            self.set_status(500)
            response_body = str(ex)
        elif isinstance(ex, exceptions.TemporaryServiceError):
            self.set_status(503)
            response_body = str(ex)
        elif isinstance(ex, web.HTTPError):
            self.set_status(ex.status_code)
            response_body = {"message": str(ex)}
        elif isinstance(ex, httpclient.HTTPError):
            self.set_status(ex.code)
            response_body = {"message": ex.message}
        else:
            self.set_status(500)
            import traceback
            formatted_lines = traceback.format_exc().splitlines()
            ex = exceptions.GeneralInfoException(formatted_lines[-1])
            response_body = str(ex)

        return response_body

    def options(self, *args, **kwargs):
        options_list = [OPTIONS]

        if self.__class__.get != BaseHandler.get:
            options_list.append(GET)

        if self.__class__.post != BaseHandler.post:
            options_list.append(POST)

        if self.__class__.put != BaseHandler.put:
            options_list.append(PUT)

        if self.__class__.delete != BaseHandler.delete:
            options_list.append(DELETE)

        if self.__class__.head != BaseHandler.head:
            options_list.append(HEAD)

        if self.__class__.patch != BaseHandler.patch:
            options_list.append(PATCH)

        self.set_header('Access-Control-Allow-Methods',
                        ', '.join(options_list))
예제 #4
0
class BaseHandler(web.RequestHandler):  # pylint: disable=too-many-public-methods
    """
    BaseHandler
    """
    def __init__(self, application, request, **kwargs):
        """
        Constructor
        """
        super(BaseHandler, self).__init__(application, request, **kwargs)
        self.context = None

    def data_received(self, chunk):
        pass

    def initialize(self, application_settings, handler=None):  # pylint: disable=arguments-differ
        self.application_settings = application_settings
        self.handler = handler
        self.request_id = self.request.headers.get(
            constants.REQUEST_ID_HTTP_HEADER)

        config.dictConfig(settings.LOGGING)
        logger = getLogger(settings.LOGGER_NAME)

        environment_name = 'MFS_ENV'

        environment = os.environ.get(environment_name)
        if not environment:
            raise exceptions.GeneralInfoException(
                '{0} environment variable not found'.format(environment_name))
        self.environment = environment

        session_info = {
            'environment': environment,
            'service': self.settings.get('service_name'),
            'handler': handler,
            'requestId': self.request_id
        }
        self.support = Support(logger, session_info)

        self.resource_name = "{0}_{1}".format(session_info['service'],
                                              handler if handler else '')

    def prepare(self):
        """
        Called at the beginning of a request before get/post/etc.
        Override this method to perform common initialization regardless of the
        request method
        """

        try:
            self.process_query()
            self.process_headers()
            self.process_body()

            request = self.request

            self.support.notify_debug("[BaseHandler] request: %s %s" %
                                      (str(request.method), str(request.uri)))
            self.support.notify_debug("[BaseHandler] query: %s" %
                                      str(request.query))
            self.support.notify_debug("[BaseHandler] headers: %s" %
                                      str(request.headers))
            self.support.notify_debug("[BaseHandler] body: %s" %
                                      str(request.body))

            body_size = sys.getsizeof(request.body)
            self.support.stat_increment('net.requests.total_count')
            self.support.stat_increment('net.requests.total_bytes', body_size)
            self.support.stat_increment('net.requests.' + str(request.method) +
                                        '_count')
            self.support.stat_increment(
                'net.requests.' + str(request.method) + '_bytes', body_size)

        except exceptions.InfoException as ex:
            self.support.notify_error(ex)
            self.build_response(ex)
        except Exception as ex:  # pylint: disable=W0703
            self.support.notify_error(ex)
            self.build_response(ex)

    def set_default_headers(self):
        self.set_header("Server", "Miramar Web Server")
        self.set_header(
            'Access-Control-Allow-Headers', 'Authorization, ' +
            'Content-Type, ' + constants.REQUEST_ID_HTTP_HEADER)
        self.set_header('Access-Control-Allow-Credentials', 'true')
        self.set_header('Access-Control-Allow-Origin', '*')
        self.set_header('Access-Control-Max-Age', '1728000')

    def process_headers(self, required_headers=None):
        """
        Process the request headers to validate if the headers in required_headers
        come in the request.
        Overwrite this method to extend this behavior or to change it at all.
        """

        if required_headers is None:
            required_headers = []
        else:
            pass

        if (self.request.method == 'POST') or (self.request.method == 'PUT'):
            required_headers.append('Content-Type')
        else:
            pass

        missing_headers = []
        for header in required_headers:
            if self.request.headers.get(header) is None:
                missing_headers.append(header)
            else:
                pass

        if len(missing_headers):
            raise exceptions.MissingArgumentValue(
                'these headers are required: %s' % missing_headers)
        else:
            pass

    def process_query(self, supported_query_attributes=None):
        """
        Process the request query.
        Overwrite this method to extend this behavior or to change it at all.
        """
        if supported_query_attributes:
            processed_query = self.request.arguments
            unsupported_attributes = list(
                set(processed_query.keys()) - set(supported_query_attributes))
            if unsupported_attributes:
                raise exceptions.InvalidArgument(
                    'The following query parameters are not supported: %s' %
                    unsupported_attributes)

    def process_body(self):
        """
        Process the request body to validate if it is valid based on the
        Content-Type header.
        Overwrite this method to extend this behavior or to change it at all.
        """

        body = self.request.body
        method = self.request.method

        if method == 'POST' or method == 'PUT':
            content_type = self.request.headers.get('Content-Type')

            if content_type.startswith('application/json'):
                try:
                    processed_body = json.loads(
                        body, object_pairs_hook=collections.OrderedDict)
                except (TypeError, ValueError) as ex:
                    raise exceptions.InvalidArgument('invalid body: %s' % ex)
            else:
                processed_body = self.request.arguments
        else:
            processed_body = None

        self.request.body_arguments = processed_body

    def build_response(self, result, status_code=None):
        """
        Build the response data with the required format according to result
        """
        self._build_response_internal(True, result, status_code)

    def build_response_without_format(self, result, status_code=None):
        """
        Build the response data with the required format according to result
        """
        self._build_response_internal(False, result, status_code)

    def _build_response_internal(self, apply_format, result, status_code=None):
        """
        Build the response data with the required format according to result
        """

        if apply_format:
            self.set_header("Content-Type", "application/json")

        if isinstance(result, Exception):
            body = self._build_response_from_exception(result)
            self.write(body)
        else:
            if apply_format:
                body = json.dumps(result)
            else:
                body = result

            if self.request.method == 'GET':
                self.set_status(
                    status_code if status_code is not None else 200)
                self.write(body)
            elif self.request.method == 'POST':
                self.set_status(
                    status_code if status_code is not None else 201)
                self.write(body)
            elif self.request.method == 'PUT':
                self.set_status(
                    status_code if status_code is not None else 204)
            elif self.request.method == 'DELETE':
                self.set_status(
                    status_code if status_code is not None else 200)
            else:
                pass

        if self.request_id:
            self.set_header(constants.REQUEST_ID_HTTP_HEADER, self.request_id)

        self.support.stat_increment('net.responses.total_count')
        self.support.stat_increment('net.responses.total_bytes',
                                    sys.getsizeof(body))

        self.finish()

    def _build_response_from_exception(self, ex):
        """
        Build HTTP response from an exception
        """
        if isinstance(ex, exceptions.BadRequestBase):
            self.set_status(400)
            response_body = str(ex)
        elif isinstance(ex, exceptions.UnauthorizedBase):
            self.set_status(401)
            response_body = str(ex)
        elif isinstance(ex, exceptions.ForbiddenBase):
            self.set_status(403)
            response_body = str(ex)
        elif isinstance(ex, exceptions.NotFoundBase):
            self.set_status(404)
            response_body = str(ex)
        elif isinstance(ex, exceptions.PermanentServiceError):
            self.set_status(500)
            response_body = str(ex)
        elif isinstance(ex, exceptions.TemporaryServiceError):
            self.set_status(503)
            response_body = str(ex)
        elif isinstance(ex, web.HTTPError):
            self.set_status(ex.status_code)
            response_body = {"message": str(ex)}
        elif isinstance(ex, httpclient.HTTPError):
            self.set_status(ex.code)
            response_body = {"message": ex.message}
        else:
            self.set_status(500)
            import traceback
            formatted_lines = traceback.format_exc().splitlines()
            ex = exceptions.GeneralInfoException(formatted_lines[-1])
            response_body = str(ex)

        return response_body

    def options(self, *args, **kwargs):
        options_list = [OPTIONS]

        if self.__class__.get != BaseHandler.get:
            options_list.append(GET)

        if self.__class__.post != BaseHandler.post:
            options_list.append(POST)

        if self.__class__.put != BaseHandler.put:
            options_list.append(PUT)

        if self.__class__.delete != BaseHandler.delete:
            options_list.append(DELETE)

        if self.__class__.head != BaseHandler.head:
            options_list.append(HEAD)

        if self.__class__.patch != BaseHandler.patch:
            options_list.append(PATCH)

        self.set_header('Access-Control-Allow-Methods',
                        ', '.join(options_list))