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
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)
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
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()
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
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)
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
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
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})
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
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
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})
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")