def __call__(self, environ, start_response): host = environ.get("HTTP_HOST", environ.get("SERVER_NAME")).lower() if ":" in host: host, port = host.split(":", 1) else: if environ["wsgi.url_scheme"] == "http": port = "80" else: port = "443" path_info = environ["PATH_INFO"] path_info = self.normalize_url(path_info, False)[1] # The MIME type for the response is determined in one of two ways: # 1) URL path suffix (eg /servers/detail.json) # 2) Accept header (eg application/json;q=0.8, application/xml;q=0.2) # The API version is determined in one of three ways: # 1) URL path prefix (eg /v1.1/tenant/servers/detail) # 2) Content-Type header (eg application/json;version=1.1) # 3) Accept header (eg application/json;q=0.8;version=1.1) supported_content_types = list(wsgi.get_supported_content_types()) mime_type, app, app_url = self._path_strategy(host, port, path_info) # Accept application/atom+xml for the index query of each API # version mount point as well as the root index if (app_url and app_url + "/" == path_info) or path_info == "/": supported_content_types.append("application/atom+xml") if not app: app = self._content_type_strategy(host, port, environ) if not mime_type or not app: possible_mime_type, possible_app = self._accept_strategy(host, port, environ, supported_content_types) if possible_mime_type and not mime_type: mime_type = possible_mime_type if possible_app and not app: app = possible_app if not mime_type: mime_type = "application/json" if not app: # Didn't match a particular version, probably matches default app, app_url = self._match(host, port, path_info) if app: app = self._munge_path(app, path_info, app_url) if app: environ["nova.best_content_type"] = mime_type return app(environ, start_response) LOG.debug("Could not find application for %s", environ.PATH_INFO) environ["paste.urlmap_object"] = self return self.not_found_application(environ, start_response)
def _path_strategy(self, host, port, path_info): """Check path suffix for MIME type and path prefix for API version.""" mime_type = app = app_url = None parts = path_info.rsplit(".", 1) if len(parts) > 1: possible_type = "application/" + parts[1] if possible_type in wsgi.get_supported_content_types(): mime_type = possible_type parts = path_info.split("/") if len(parts) > 1: possible_app, possible_app_url = self._match(host, port, path_info) # Don't use prefix if it ends up matching default if possible_app and possible_app_url: app_url = possible_app_url app = self._munge_path(possible_app, path_info, app_url) return mime_type, app, app_url