Exemplo n.º 1
0
class BaseHandler(tornado.web.RequestHandler):
    '''
    General request handler.
    '''

    def initialize(self, registry):
        self.registry = registry
        if self.registry.get_hostname() == '':
            self.registry.set_hostname(self.request.protocol + '://' +
                                       self.request.host)

    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__(application, request, **kwargs)
        # This ensures that at least one registry is loaded in case initialize
        # is not called for some reason...
        self.registry = NonePersistentRegistry()

        if self.registry.get_hostname() == '':
            self.registry.set_hostname(self.request.protocol + '://' +
                                       self.request.host)

    def extract_http_data(self):
        '''
        Extracts all necessary information from the HTTP envelop. Minimize the
        data which is carried around inside of the service. Also ensures that
        the names are always equal - When deployed in Apache the names of the
        Headers change.
        '''
        heads = {}
        headers = self.request.headers
        if 'Category' in headers:
            heads['Category'] = headers['Category']
        if 'X-Occi-Attribute' in headers:
            heads['X-OCCI-Attribute'] = headers['X-Occi-Attribute']
        if 'X-Occi-Location' in headers:
            heads['X-OCCI-Location'] = headers['X-Occi-Location']
        if 'Link' in headers:
            heads['Link'] = headers['Link']
        if self.request.body is not '':
            body = self.request.body.strip()
        else:
            body = ''

        return heads, body

    def get_renderer(self, content_type):
        '''
        Returns the proper rendering parser.

        content_type -- String with either either Content-Type or Accept.
        '''
        try:
            return self.registry.get_renderer(
                                            self.request.headers[content_type])
        except KeyError:
            return self.registry.get_renderer(self.registry.get_default_type())

    def response(self, status, mime_type, headers, body='OK'):
        '''
        Will create a response and send it to the client.

        status -- The status code.
        mime_type -- Sets the Content-Type of the response.
        headers -- The HTTP headers.
        body -- The text for the body (default: ok).
        '''
        self.set_header('Server', VERSION)
        self.set_header('Content-Type', mime_type)
        self.set_status(status)
        if headers is not None:
            for item in headers.keys():
                self._headers[item] = headers[item]
        self.write(body)
        self.finish('\n')

    def get_error_html(self, status_code, **kwargs):
        self.set_header('Server', VERSION)
        self.set_header('Content-Type', self.registry.get_default_type())
        exception = sys.exc_info()[1]
        msg = str(exception)
        self.set_status(status_code)
        return msg

    def parse_action(self):
        '''
        Retrieves the Action which was given in the request.
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        action = rendering.to_action(headers, body)

        return action

    def parse_filter(self):
        '''
        Retrieve any attributes or categories which where provided in the
        request for filtering.
        '''
        headers, body = self.extract_http_data()

        attr = 'X-OCCI-Attribute'
        if  attr not in headers and 'Category' not in headers and body == '':
            return [], {}

        rendering = self.get_renderer(CONTENT_TYPE)

        categories, attributes = rendering.get_filters(headers, body)

        return categories, attributes

    def parse_entity(self, def_kind=None):
        '''
        Retrieves the entity which was rendered within the request.

        def_kind -- Indicates if the request can be incomplete (False).
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        entity = rendering.to_entity(headers, body, def_kind)

        return entity

    def parse_entities(self):
        '''
        Retrieves a set of entities which was rendered within the request.
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        entities = rendering.to_entities(headers, body)

        return entities

    def parse_mixins(self):
        '''
        Retrieves a mixin from a request.
        '''
        headers, body = self.extract_http_data()
        rendering = self.get_renderer(CONTENT_TYPE)

        mixin = rendering.to_mixins(headers, body)

        return mixin

    def render_entity(self, entity):
        '''
        Renders a single entity to the client.

        entity -- The entity which should be rendered.
        '''
        rendering = self.get_renderer(ACCEPT)

        headers, body = rendering.from_entity(entity)

        self.response(200, rendering.mime_type, headers, body)

    def render_entities(self, entities, key):
        '''
        Renders a list of entities to the client.

        entities -- The entities which should be rendered.
        '''
        rendering = self.get_renderer(ACCEPT)

        headers, body = rendering.from_entities(entities, key)

        self.response(200, rendering.mime_type, headers, body)

    def render_categories(self, categories):
        '''
        Renders a list of categories to the client.

        categories -- The categories which should be rendered.
        '''
        rendering = self.get_renderer(ACCEPT)

        headers, body = rendering.from_categories(categories)

        self.response(200, rendering.mime_type, headers, body)