예제 #1
0
    def _get_method_name(self, has_iden):
        '''
        Return resource object based on the HTTP method

        :param has_iden: specifies if requested url has iden (i.e /res/ vs
        /res/1)
        :type has_iden: bool
        :raises errors.MethodNotAllowedError: if HTTP method is not supprted
        :returns: name of the resource method name
        :rtype: str
        '''
        method = self.request.method
        method = self.request.headers.get('HTTP_X_HTTP_METHOD_OVERRIDE',
                                          method)
        method_name = self.method_map.get(method.lower())

        if not method_name:
            raise errors.MethodNotAllowedError(
                'Method "{}" is not supported'.format(self.request.method))

        if isinstance(method_name, tuple):
            method_name = method_name[has_iden]

        if not has_iden and self._iden_required(method_name):
            raise errors.BadRequestError('Given method requires iden')

        if has_iden and not self._iden_required(method_name):
            raise errors.BadRequestError('Given method shouldn\'t have iden')

        return method_name
예제 #2
0
    def _get_payload(self, method_name):
        '''
        Returns a validated and parsed payload data for request

        :param method_name: name of the method
        :type method_name: str
        :raises restea.errors.BadRequestError: unparseable data
        :raises restea.errors.BadRequestError: payload is not mappable
        :raises restea.errors.BadRequestError: validation of fields not passed
        :returns: validated data passed to resource
        :rtype: dict
        '''
        if not self.request.data:
            return {}

        try:
            payload_data = self.formatter.unserialize(self.request.data)
        except formats.LoadError:
            raise errors.BadRequestError('Fail to load the data')

        if not isinstance(payload_data, collections.Mapping):
            raise errors.BadRequestError(
                'Data should be key -> value structure')

        try:
            return self.fields.validate(method_name, payload_data)
        except fields.FieldSet.Error as e:
            raise errors.BadRequestError(str(e))
        except fields.FieldSet.ConfigurationError as e:
            raise errors.ServerError(str(e))
예제 #3
0
    def process(self, *args, **kwargs):
        '''
        Processes the payload and maps HTTP method to resource object methods
        and calls the method

        :raises restea.errors.BadRequestError: wrong self.formatter type
        :raises restea.errors.ServerError: Some unhandled exception in
        resource method implementation or formatter serialization error

        :returns: serialized data to be returned to client
        :rtype: str
        '''
        if not self._is_valid_formatter:
            raise errors.BadRequestError('Not recognizable format')

        method_name = self._get_method_name(has_iden=bool(args or kwargs))
        self.payload = self._get_payload(method_name)
        method = self._get_method(method_name)
        method = self._apply_decorators(method)

        self.prepare()
        response = method(self, *args, **kwargs)
        response = self.finish(response)

        try:
            return self.formatter.serialize(response)
        except formats.LoadError:
            raise errors.ServerError('Service can\'t respond with this format')
예제 #4
0
def test_dispatch_exception(process_mock):
    resource, _, _ = create_resource_helper()
    resource.process.side_effect = errors.ServerError('Error!')

    res, status, content_type = resource.dispatch()
    assert res == json.dumps({'error': 'Error!'})
    assert status == 503
    assert content_type == 'application/json'

    resource.process.side_effect = errors.BadRequestError('Wrong!', code=101)

    res, status, content_type = resource.dispatch()
    assert res == json.dumps({'error': 'Wrong!', 'code': 101})
    assert status == 400
    assert content_type == 'application/json'
예제 #5
0
    def _get_method(self, method_name):
        '''
        Returns method based on a name

        :param method_name: name of the method
        :type method_name: str
        :raises errors.BadRequestError: method is not implemented for a given
        resource
        :returns: method of the REST resource object
        :rtype: function
        '''
        method_exists = hasattr(self, method_name)
        if not method_exists:
            msg = 'Method "{}" is not implemented for a given endpoint'
            raise errors.BadRequestError(msg.format(self.request.method))
        return getattr(type(self), method_name)
예제 #6
0
def test_dispatch_exception(process_mock):
    resource, _, _ = create_resource_helper()

    resource.process.side_effect = errors.ServerError('Error!')
    res, status, content_type, headers = resource.dispatch()
    assert res == json.dumps({'error': 'Error!'})
    assert status == 503
    assert content_type == 'application/json'
    assert headers == {}

    resource.process.side_effect = errors.BadRequestError('Wrong!', code=101)
    res, status, content_type, headers = resource.dispatch()
    expected_response = {'error': 'Wrong!', 'code': 101}
    assert set(json.loads(res).items()) == set(expected_response.items())
    assert status == 400
    assert content_type == 'application/json'
    assert headers == {}

    resource.process.side_effect = errors.ForbiddenError('Unauthorized!',
                                                         login_path='/login')
    res, status, content_type, headers = resource.dispatch()
    expected_response = {'error': 'Unauthorized!', 'login_path': '/login'}
    assert set(json.loads(res).items()) == set(expected_response.items())
    assert status == 403
    assert content_type == 'application/json'
    assert headers == {}

    resource.process.side_effect = errors.NotFoundError(
        'Not found!', code=101, redirect_path='/search')
    res, status, content_type, headers = resource.dispatch()
    expected_response = {
        'error': 'Not found!',
        'code': 101,
        'redirect_path': '/search'
    }
    assert set(json.loads(res).items()) == set(expected_response.items())
    assert status == 404
    assert content_type == 'application/json'
    assert headers == {}