def process_request(req): """Process api request: 1. Define if this is request for available versions or not 2. If it is not version request check extract version 3. Validate available version and add version info to request """ args = {'method': req.method, 'path': req.path, 'accept': req.accept} LOG.debug( "Determining version of request: %(method)s %(path)s " "Accept: %(accept)s", args) # determine if this is request for versions if req.path_info in ('/versions', '/'): return artifacts_versions.Controller.index(req) # determine api version from request req_version = GlareVersionNegotiationFilter.get_version_from_accept( req.accept) if req_version is None: # determine api version from microversion header LOG.debug("Determine version from microversion header.") req_version = microversion_parse.get_version( req.headers, service_type=GlareVersionNegotiationFilter.SERVICE_TYPE) # validate microversions header req.api_version_request = \ GlareVersionNegotiationFilter._get_api_version_request( req_version) req_version = req.api_version_request.get_string() LOG.debug("Matched version: %s", req_version) LOG.debug('new path %s', req.path_info)
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='accelerator') minimal_version = (2, 0) if version_str is None: # If requested header is wrong, Cyborg 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 if len(version) != 2: raise exc.HTTPNotAcceptable("Invalid value for %s header" % Version.current_api_version) return version
def _check_version_request(self, req, controller): """Set API version request based on the request header and controller. :param req: The webob.Request object. :param controller: The API version controller. :returns: ``None`` :raises: ``HTTPBadRequest`` if API version string is bad. """ api_version = mp.get_version(req.headers, service_type='clustering') if api_version is None: api_version = controller.DEFAULT_API_VERSION elif api_version.lower() == 'latest': req.version_request = controller.max_api_version() return try: ver = vr.APIVersionRequest(api_version) except exception.InvalidAPIVersionString as e: raise webob.exc.HTTPBadRequest(six.text_type(e)) if not ver.matches(controller.min_api_version(), controller.max_api_version()): raise exception.InvalidGlobalAPIVersion( req_ver=api_version, min_ver=six.text_type(controller.min_api_version()), max_ver=six.text_type(controller.max_api_version())) req.version_request = ver
def test_capitalized_headers(self): headers = {'X-Openstack-Ironic-Api-Version': '123.456'} version = microversion_parse.get_version( headers, service_type='ironic', legacy_headers=['X-Openstack-Ironic-Api-Version']) self.assertEqual('123.456', version)
def set_api_version_request(self): """Set API version request based on the request header information.""" hdr_string = microversion_parse.get_version( self.headers, service_type='compute', legacy_headers=[LEGACY_API_VERSION_REQUEST_HEADER]) if hdr_string is None: self.api_version_request = api_version.APIVersionRequest( api_version.DEFAULT_API_VERSION) elif hdr_string == 'latest': # 'latest' is a special keyword which is equivalent to # requesting the maximum version of the API supported self.api_version_request = api_version.max_api_version() else: self.api_version_request = api_version.APIVersionRequest( hdr_string) # Check that the version requested is within the global # minimum/maximum of supported API versions if not self.api_version_request.matches( api_version.min_api_version(), api_version.max_api_version()): raise exception.InvalidGlobalAPIVersion( req_ver=self.api_version_request.get_string(), min_ver=api_version.min_api_version().get_string(), max_ver=api_version.max_api_version().get_string())
def test_get_version_from_environ(self): environ = {'PATH_INFO': '/foo/bar', 'HTTP_OPENSTACK_API_VERSION': 'placement 2.1', 'HTTP_CONTENT_TYPE': 'application/json'} expected_version = '2.1' headers = microversion_parse.headers_from_wsgi_environ(environ) version = microversion_parse.get_version(headers, 'placement') self.assertEqual(expected_version, version)
def get_requested_microversion(): requested_version = microversion_parse.get_version(flask.request.headers, mv.SAHARA_SERVICE_TYPE) if requested_version is None: requested_version = mv.MIN_API_VERSION elif requested_version == mv.LATEST: requested_version = mv.MAX_API_VERSION return requested_version
def test_legacy_headers_prefer(self): headers = { 'header-one': 'alpha', 'openstack-compute-api-version': '3.7', 'x-openstack-nova-api-version': ' 2.1, 9.2 ', 'header-two': 'beta', } version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['openstack-compute-api-version', 'x-openstack-nova-api-version']) self.assertEqual('3.7', version) version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['x-openstack-nova-api-version', 'openstack-compute-api-version']) self.assertEqual('9.2', version)
def test_capitalized_headers(self): headers = { 'X-Openstack-Ironic-Api-Version': '123.456' } version = microversion_parse.get_version( headers, service_type='ironic', legacy_headers=['X-Openstack-Ironic-Api-Version']) self.assertEqual('123.456', version)
def get_requested_microversion(): requested_version = microversion_parse.get_version( flask.request.headers, api_version.RESERVATION_SERVICE_TYPE) if requested_version is None: requested_version = api_version.MIN_API_VERSION elif requested_version == api_version.LATEST: requested_version = api_version.MAX_API_VERSION return requested_version
def test_unfolded_service(self): headers = [ ('header-one', 'alpha'), ('openstack-api-version', 'compute 1.0'), ('openstack-api-version', 'compute 2.0'), ('openstack-api-version', '3.0'), ] version = microversion_parse.get_version( headers, service_type='compute') self.assertEqual('2.0', version)
def test_unfolded_service(self): headers = [ ('header-one', 'alpha'), ('openstack-api-version', 'compute 1.0'), ('openstack-api-version', 'compute 2.0'), ('openstack-api-version', '3.0'), ] version = microversion_parse.get_version(headers, service_type='compute') self.assertEqual('2.0', version)
def get_requested_microversion(): requested_version = microversion_parse.get_version( flask.request.headers, mv.SAHARA_SERVICE_TYPE ) if requested_version is None: requested_version = mv.MIN_API_VERSION elif requested_version == mv.LATEST: requested_version = mv.MAX_API_VERSION return requested_version
def test_get_version_from_environ(self): environ = { 'PATH_INFO': '/foo/bar', 'HTTP_OPENSTACK_API_VERSION': 'placement 2.1', 'HTTP_CONTENT_TYPE': 'application/json' } expected_version = '2.1' headers = microversion_parse.headers_from_wsgi_environ(environ) version = microversion_parse.get_version(headers, 'placement') self.assertEqual(expected_version, version)
def test_get_version_from_environ_legacy(self): environ = {'PATH_INFO': '/foo/bar', 'HTTP_X_OPENSTACK_PLACEMENT_API_VERSION': '2.1', 'HTTP_CONTENT_TYPE': 'application/json'} expected_version = '2.1' headers = microversion_parse.headers_from_wsgi_environ(environ) version = microversion_parse.get_version( headers, 'placement', legacy_headers=['x-openstack-placement-api-version']) self.assertEqual(expected_version, version)
def test_legacy_headers_straight(self): headers = { 'header-one': 'alpha', 'openstack-compute-api-version': ' 2.1 ', 'header-two': 'beta', } version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['openstack-CoMpUte-api-version']) self.assertEqual('2.1', version)
def test_legacy_headers_folded(self): headers = wb_headers.EnvironHeaders({ 'HTTP_HEADER_ONE': 'alpha', 'HTTP_X_OPENSTACK_NOVA_API_VERSION': ' 2.1, 9.2 ', 'HTTP_HEADER_TWO': 'beta', }) version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['x-openstack-nova-api-version']) self.assertEqual('9.2', version)
def test_unfolded_in_name(self): headers = [ ('header-one', 'alpha'), ('x-openstack-nova-api-version', '1.0'), ('x-openstack-nova-api-version', '2.0'), ('openstack-telemetry-api-version', '3.0'), ] version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['x-openstack-nova-api-version']) self.assertEqual('2.0', version)
def test_legacy_headers_folded(self): headers = { 'header-one': 'alpha', 'openstack-compute-api-version': ' 2.1, 9.2 ', 'header-two': 'beta', } version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['openstack-compute-api-version']) self.assertEqual('9.2', version)
def test_older_legacy_headers(self): headers = { 'header-one': 'alpha', 'x-openstack-nova-api-version': ' 2.1, 9.2 ', 'header-two': 'beta', } version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=['openstack-nova-api-version', 'x-openstack-nova-api-version']) # We don't do x- for service types. self.assertEqual('9.2', version)
def test_get_version_from_environ_legacy(self): environ = { 'PATH_INFO': '/foo/bar', 'HTTP_X_OPENSTACK_PLACEMENT_API_VERSION': '2.1', 'HTTP_CONTENT_TYPE': 'application/json' } expected_version = '2.1' headers = microversion_parse.headers_from_wsgi_environ(environ) version = microversion_parse.get_version( headers, 'placement', legacy_headers=['x-openstack-placement-api-version']) self.assertEqual(expected_version, version)
def test_older_legacy_headers(self): headers = { 'header-one': 'alpha', 'x-openstack-nova-api-version': ' 2.1, 9.2 ', 'header-two': 'beta', } version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=[ 'openstack-nova-api-version', 'x-openstack-nova-api-version' ]) # We don't do x- for service types. self.assertEqual('9.2', version)
def test_preference(self): headers = { 'header-one': 'alpha', 'openstack-api-version': 'compute 11.12, telemetry 9.7', 'openstack-compute-api-version': '3.7', 'x-openstack-nova-api-version': ' 2.1, 9.2 ', 'header-two': 'beta', } version = microversion_parse.get_version( headers, service_type='compute', legacy_headers=[ 'openstack-compute-api-version', 'x-openstack-nova-api-version' ]) self.assertEqual('11.12', version)
def extract_version(headers): """Extract the microversion from Version.HEADER There may be multiple headers and some which don't match our service. """ found_version = microversion_parse.get_version(headers, service_type=SERVICE_TYPE) version_string = found_version or min_version_string() request_version = parse_version_string(version_string) # We need a version that is in VERSION and within MIX and MAX. # This gives us the option to administratively disable a # version if we really need to. if str(request_version) in VERSIONS and request_version.matches(): return request_version raise ValueError("Unacceptable version header: %s" % version_string)
def extract_version(headers): """Extract the microversion from Version.HEADER There may be multiple headers and some which don't match our service. """ found_version = microversion_parse.get_version(headers, service_type=SERVICE_TYPE) version_string = found_version or min_version_string() request_version = parse_version_string(version_string) # We need a version that is in VERSION and within MIX and MAX. # This gives us the option to administratively disable a # version if we really need to. if (str(request_version) in VERSIONS and request_version.matches()): return request_version raise ValueError('Unacceptable version header: %s' % version_string)
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 process_request(self, req): """Process api request: 1. Define if this is request for available versions or not 2. If it is not version request check extract version 3. Validate available version and add version info to request """ args = {'method': req.method, 'path': req.path, 'accept': req.accept} LOG.debug("Determining version of request: %(method)s %(path)s " "Accept: %(accept)s", args) # determine if this is request for versions if req.path_info in ('/versions', '/'): is_multi = req.path_info == '/' return artifacts_versions.Controller.index( req, is_multi=is_multi) # determine api version from request req_version = get_version_from_accept(req.accept, self.vnd_mime_type) if req_version is None: # determine api version for v0.1 from url if req.path_info_peek() == 'v0.1': req_version = 'v0.1' else: # determine api version from microversion header LOG.debug("Determine version from microversion header.") req_version = microversion_parse.get_version( req.headers, service_type=self.SERVICE_TYPE) # validate versions and add version info to request if req_version == 'v0.1': req.environ['api.version'] = 0.1 else: # validate microversions header req.api_version_request = self._get_api_version_request( req_version) req_version = req.api_version_request.get_string() LOG.debug("Matched version: %s", req_version) LOG.debug('new path %s', req.path_info)
def check_version_request(self, req): """Set API version request based on the request header.""" api_version = microversion_parse.get_version(req.headers, service_type='clustering') if api_version is None: api_version = wsgi.DEFAULT_API_VERSION elif api_version.lower() == 'latest': req.version_request = os_ver.max_api_version() return try: ver = vr.APIVersionRequest(api_version) except exception.InvalidAPIVersionString as e: raise webob.exc.HTTPBadRequest(six.text_type(e)) if not ver.matches(os_ver.min_api_version(), os_ver.max_api_version()): raise exception.InvalidGlobalAPIVersion( req_ver=api_version, min_ver=six.text_type(os_ver.min_api_version()), max_ver=six.text_type(os_ver.max_api_version())) req.version_request = ver
def process_request(self, req): """Process api request: 1. Define if this is request for available versions or not 2. If it is not version request check extract version 3. Validate available version and add version info to request """ args = {'method': req.method, 'path': req.path, 'accept': req.accept} LOG.debug( "Determining version of request: %(method)s %(path)s " "Accept: %(accept)s", args) # determine if this is request for versions if req.path_info in ('/versions', '/'): is_multi = req.path_info == '/' return artifacts_versions.Controller.index(req, is_multi=is_multi) # determine api version from request req_version = get_version_from_accept(req.accept, self.vnd_mime_type) if req_version is None: # determine api version for v0.1 from url if req.path_info_peek() == 'v0.1': req_version = 'v0.1' else: # determine api version from microversion header LOG.debug("Determine version from microversion header.") req_version = microversion_parse.get_version( req.headers, service_type=self.SERVICE_TYPE) # validate versions and add version info to request if req_version == 'v0.1': req.environ['api.version'] = 0.1 else: # validate microversions header req.api_version_request = self._get_api_version_request( req_version) req_version = req.api_version_request.get_string() LOG.debug("Matched version: %s", req_version) LOG.debug('new path %s', req.path_info)
def test_no_headers(self): headers = {} version = microversion_parse.get_version(headers, service_type='compute') self.assertEqual(None, version)
def test_no_headers(self): headers = {} version = microversion_parse.get_version( headers, service_type='compute') self.assertEqual(None, version)