Esempio n. 1
0
    def parse_headers(headers, default_version, latest_version):
        """Determine the API version requested based on the headers supplied.

        :param headers: webob headers
        :param default_version: version to use if not specified in headers
        :param latest_version: version to use if latest is requested
        :returns: a tuple of (major, minor) version numbers
        :raises: webob.HTTPNotAcceptable
        """
        version_str = headers.get(Version.string, default_version)

        if version_str.lower() == 'latest':
            parse_str = latest_version
        else:
            parse_str = version_str

        try:
            version = tuple(int(i) for i in parse_str.split('.'))
        except ValueError:
            version = ()

        if len(version) != 2:
            raise exc.HTTPNotAcceptable(
                _("Invalid value for %s header") % Version.string)
        return version
Esempio n. 2
0
 def _check_version(self, version, headers=None):
     if headers is None:
         headers = {}
     # ensure that major version in the URL matches the header
     if version.major != BASE_VERSION:
         raise exc.HTTPNotAcceptable(_(
             "Mutually exclusive versions requested. Version %(ver)s "
             "requested but not supported by this service. The supported "
             "version range is: [%(min)s, %(max)s].") % {'ver': version,
             'min': MIN_VER_STR, 'max': MAX_VER_STR}, headers=headers)
     # ensure the minor version is within the supported range
     if version < MIN_VER or version > MAX_VER:
         raise exc.HTTPNotAcceptable(_(
             "Version %(ver)s was requested but the minor version is not "
             "supported by this service. The supported version range is: "
             "[%(min)s, %(max)s].") % {'ver': version, 'min': MIN_VER_STR,
                                       'max': MAX_VER_STR}, headers=headers)
Esempio n. 3
0
def formatter_for_request(req):
    '''Return a formatter that encodes to the preferred type of the client.

    The result is a pair of function and actual MIME type.'''
    ctype = req.accept.best_match(formatter_qualities)
    try:
        return llsd_formatters[ctype], ctype
    except KeyError:
        raise exc.HTTPNotAcceptable().exception
Esempio n. 4
0
    def _check_version(self, version):
        # ensure that major version in the URL matches the header
        if version.major != 1:
            raise exc.HTTPNotAcceptable(
                _("Mutually exclusive versions requested. Version %(ver)s "
                  "requested but not supported by this service.") %
                {'ver': version})
        # ensure the minor version is within the supported range
        if version.minor < MIN_VER or version.minor > MAX_VER:
            raise exc.HTTPNotAcceptable(
                _("Unsupported minor version requested. This API service "
                  "supports the following version range: "
                  "[%(min)s, %(max)s].") % {
                      'min': MIN_VER,
                      'max': MAX_VER
                  })

        version.set_min_max(MIN_VER, MAX_VER)
def consume_params(request):
    # we want to deserialize "heh" and "yeah".
    if 'application/json' in request.accept:
        for param in request.params.keys():
            try:
                json.loads(request.params[param])
            except ValueError:
                return  exc.HTTPBadRequest()
        return ok(request)
    else:
        raise exc.HTTPNotAcceptable()
Esempio n. 6
0
def formatter_for_request(req):
    '''Return a formatter that encodes to the preferred type of the client.

    The result is a pair of function and actual MIME type.'''

    for ctype in req.accept.best_matches('application/llsd+xml'):
        try:
            return llsd_formatters[ctype], ctype
        except KeyError:
            pass
    else:
        raise exc.HTTPNotAcceptable().exception
Esempio n. 7
0
def code2exception(code, detail):
    """Transforms a code + detail into a WebOb exception"""
    if code == 400:
        return exc.HTTPBadRequest(detail)
    if code == 401:
        return exc.HTTPUnauthorized(detail)
    if code == 402:
        return exc.HTTPPaymentRequired(detail)
    if code == 403:
        return exc.HTTPForbidden(detail)
    if code == 404:
        return exc.HTTPNotFound(detail)
    if code == 405:
        return exc.HTTPMethodNotAllowed(detail)
    if code == 406:
        return exc.HTTPNotAcceptable(detail)
    if code == 407:
        return exc.HTTPProxyAuthenticationRequired(detail)
    if code == 408:
        return exc.HTTPRequestTimeout(detail)
    if code == 409:
        return exc.HTTPConflict(detail)
    if code == 410:
        return exc.HTTPGone(detail)
    if code == 411:
        return exc.HTTPLengthRequired(detail)
    if code == 412:
        return exc.HTTPPreconditionFailed(detail)
    if code == 413:
        return exc.HTTPRequestEntityTooLarge(detail)
    if code == 414:
        return exc.HTTPRequestURITooLong(detail)
    if code == 415:
        return exc.HTTPUnsupportedMediaType(detail)
    if code == 416:
        return exc.HTTPRequestRangeNotSatisfiable(detail)
    if code == 417:
        return exc.HTTPExpectationFailed(detail)
    if code == 500:
        return exc.HTTPInternalServerError(detail)
    if code == 501:
        return exc.HTTPNotImplemented(detail)
    if code == 502:
        return exc.HTTPBadGateway(detail)
    if code == 503:
        return exc.HTTPServiceUnavailable(detail)
    if code == 504:
        return exc.HTTPGatewayTimeout(detail)
    if code == 505:
        return exc.HTTPVersionNotSupported(detail)

    raise NotImplementedError(code)
Esempio n. 8
0
    def parse_headers(headers):
        """Determine the API version requested based on the headers supplied.

        :param headers: webob headers
        :returns: a tupe of (major, minor) version numbers
        :raises: webob.HTTPNotAcceptable
        """
        try:
            version = tuple(
                int(i) for i in headers.get(Version.string, '1.0').split('.'))
        except ValueError:
            version = ()
        if len(version) != 2:
            raise exc.HTTPNotAcceptable(
                _("Invalid value for X-OpenStack-Ironic-API-Version "
                  "header."))
        return version
Esempio n. 9
0
    def parse_headers(headers):
        """Determine the API version requested based on the headers supplied.

        :param headers: webob headers
        :returns: a tupe of (major, minor) version numbers
        :raises: webob.HTTPNotAcceptable
        """
        try:
            # default to the minimum supported version,  but don't actually
            # import v1.__init__ here because that would be circular...
            version = tuple(int(i) for i in headers.get(
                    Version.string, '1.1').split('.'))
        except ValueError:
            version = ()
        if len(version) != 2:
            raise exc.HTTPNotAcceptable(_(
                "Invalid value for X-OpenStack-Ironic-API-Version "
                "header."))
        return version
Esempio n. 10
0
        def version_select():
            """Select the correct method based on version

            @return: Returns the correct versioned method
            @raises: HTTPNotAcceptable if there is no method which
                 matches the name and version constraints
            """

            from pecan import request
            ver = request.version

            func_list = self.versioned_methods[key]
            for func in func_list:
                if ver.matches(func.start_version, func.end_version):
                    return func.func

            raise exc.HTTPNotAcceptable(_(
                "Version %(ver)s was requested but the requested API %(api)s "
                "is not supported for this version.") % {'ver': ver,
                                                         'api': key})
Esempio n. 11
0
    def parse_headers(headers, default_version, latest_version):
        """Determine the API version requested based on the headers supplied.

        :param headers: webob headers
        :param default_version: version to use if not specified in headers
        :param latest_version: version to use if latest is requested
        :returns: a tuple of (major, minor) version numbers
        :raises: webob.HTTPNotAcceptable

        """
        version_str = microversion_parse.get_version(
            headers, service_type='infra-optim')

        minimal_version = (1, 0)

        if version_str is None:
            # If requested header is wrong, Watcher answers with the minimal
            # supported version.
            return minimal_version

        if version_str.lower() == 'latest':
            parse_str = latest_version
        else:
            parse_str = version_str

        try:
            version = tuple(int(i) for i in parse_str.split('.'))
        except ValueError:
            version = minimal_version

        # NOTE (alexchadin): Old python-watcherclient sends requests with
        # value of version header is "1". It should be transformed to 1.0 as
        # it was supposed to be.
        if len(version) == 1 and version[0] == 1:
            version = minimal_version

        if len(version) != 2:
            raise exc.HTTPNotAcceptable("Invalid value for %s header" %
                                        Version.string)
        return version
Esempio n. 12
0
    def find_controller(self, state):
        '''
        The main request handler for Pecan applications.
        '''
        # get a sorted list of hooks, by priority (no controller hooks yet)
        req = state.request
        pecan_state = req.pecan

        # store the routing path for the current application to allow hooks to
        # modify it
        pecan_state['routing_path'] = path = req.path_info

        # handle "on_route" hooks
        self.handle_hooks(self.hooks, 'on_route', state)

        # lookup the controller, respecting content-type as requested
        # by the file extension on the URI
        pecan_state['extension'] = None

        # attempt to guess the content type based on the file extension
        if self.guess_content_type_from_ext \
                and not pecan_state['content_type'] \
                and '.' in path:
            _, extension = splitext(path.rstrip('/'))

            # preface with a letter to ensure compat for 2.5
            potential_type = guess_type('x' + extension)[0]

            if extension and potential_type is not None:
                path = ''.join(path.rsplit(extension, 1))
                pecan_state['extension'] = extension
                pecan_state['content_type'] = potential_type

        controller, remainder = self.route(req, self.root, path)
        cfg = _cfg(controller)

        if cfg.get('generic_handler'):
            raise exc.HTTPNotFound

        # handle generic controllers
        im_self = None
        if cfg.get('generic'):
            im_self = six.get_method_self(controller)
            handlers = cfg['generic_handlers']
            controller = handlers.get(req.method, handlers['DEFAULT'])
            handle_security(controller, im_self)
            cfg = _cfg(controller)

        # add the controller to the state so that hooks can use it
        state.controller = controller

        # if unsure ask the controller for the default content type
        content_types = cfg.get('content_types', {})
        if not pecan_state['content_type']:
            # attempt to find a best match based on accept headers (if they
            # exist)
            accept = getattr(req.accept, 'header_value', '*/*')
            if accept == '*/*' or (accept.startswith('text/html,') and list(
                    content_types.keys()) in self.SIMPLEST_CONTENT_TYPES):
                pecan_state['content_type'] = cfg.get('content_type',
                                                      'text/html')
            else:
                best_default = acceptparse.MIMEAccept(accept).best_match(
                    content_types.keys())

                if best_default is None:
                    msg = "Controller '%s' defined does not support " + \
                          "content_type '%s'. Supported type(s): %s"
                    logger.error(
                        msg %
                        (controller.__name__, pecan_state['content_type'],
                         content_types.keys()))
                    raise exc.HTTPNotAcceptable()

                pecan_state['content_type'] = best_default
        elif cfg.get('content_type') is not None and \
                pecan_state['content_type'] not in content_types:

            msg = "Controller '%s' defined does not support content_type " + \
                  "'%s'. Supported type(s): %s"
            logger.error(msg %
                         (controller.__name__, pecan_state['content_type'],
                          content_types.keys()))
            raise exc.HTTPNotFound

        # fetch any parameters
        if req.method == 'GET':
            params = req.GET
        elif req.content_type in ('application/json',
                                  'application/javascript'):
            try:
                if not isinstance(req.json, dict):
                    raise TypeError('%s is not a dict' % req.json)
                params = NestedMultiDict(req.GET, req.json)
            except (TypeError, ValueError):
                params = req.params
        else:
            params = req.params

        # fetch the arguments for the controller
        args, varargs, kwargs = self.get_args(state, params.mixed(), remainder,
                                              cfg['argspec'], im_self)
        state.arguments = Arguments(args, varargs, kwargs)

        # handle "before" hooks
        self.handle_hooks(self.determine_hooks(controller), 'before', state)

        return controller, args + varargs, kwargs
Esempio n. 13
0
    def _no_version_match(self, *args, **kwargs):
        from pecan import request

        raise exc.HTTPNotAcceptable(
            _("Version %(ver)s was requested but the requested API is not "
              "supported for this version.") % {'ver': request.version})
Esempio n. 14
0
 def handle_GET(self, req, *args, **kwargs):
     if req.content_type == "application/json":
         return self.handle_json_GET(req, *args, **kwargs)
     return exc.HTTPNotAcceptable("Only json mimetypes allowed")