def _get_path(self, path, headers=None): """ Retrieve a single path within the upstream registry, and return a 2-tuple of the headers and the response body. :param path: a full http path to retrieve that will be urljoin'd to the upstream registry url. :type path: basestring :param headers: headers sent in the request :type headers: dict :return: (headers, response body) :rtype: tuple """ url = urlparse.urljoin(self.registry_url, path) _logger.debug(_('Retrieving {0}'.format(url))) request = DownloadRequest(url, StringIO()) request.headers = headers if self.token: request.headers = auth_util.update_token_auth_header( request.headers, self.token) report = self.downloader.download_one(request) # If the download was unauthorized, check report header, if basic auth is expected # retry with basic auth, otherwise attempt to get a token and try again if report.state == report.DOWNLOAD_FAILED: if report.error_report.get( 'response_code') == httplib.UNAUTHORIZED: auth_header = report.headers.get('www-authenticate') if auth_header is None: raise IOError("401 responses are expected to " "contain authentication information") elif "Basic" in auth_header: _logger.debug( _('Download unauthorized, retrying with basic authentication' )) report = self.auth_downloader.download_one(request) else: _logger.debug( _('Download unauthorized, attempting to retrieve a token.' )) self.token = auth_util.request_token( self.auth_downloader, request, auth_header, self.name) request.headers = auth_util.update_token_auth_header( request.headers, self.token) report = self.downloader.download_one(request) if report.state == report.DOWNLOAD_FAILED: # this condition was added in case the registry would not allow to access v2 endpoint # but still token would be valid for other endpoints. # see https://pulp.plan.io/issues/2643 if path == '/v2/' and report.error_report.get( 'response_code') == httplib.UNAUTHORIZED: pass else: self._raise_path_error(report) return report.headers, report.destination.getvalue()
def _get_path(self, path): """ Retrieve a single path within the upstream registry, and return a 2-tuple of the headers and the response body. :param path: a full http path to retrieve that will be urljoin'd to the upstream registry url. :type path: basestring :return: (headers, response body) :rtype: tuple """ url = urlparse.urljoin(self.registry_url, path) _logger.debug(_('Retrieving {0}'.format(url))) request = DownloadRequest(url, StringIO()) if self.token: request.headers = token_util.update_auth_header(request.headers, self.token) report = self.downloader.download_one(request) # If the download was unauthorized, attempt to get a token and try again if report.state == report.DOWNLOAD_FAILED: if report.error_report.get('response_code') == httplib.UNAUTHORIZED: _logger.debug(_('Download unauthorized, attempting to retrieve a token.')) self.token = token_util.request_token(self.token_downloader, request, report.headers) request.headers = token_util.update_auth_header(request.headers, self.token) report = self.downloader.download_one(request) if report.state == report.DOWNLOAD_FAILED: self._raise_path_error(report) return report.headers, report.destination.getvalue()
def _get_single_path(self, path): """ Retrieve a single path within the upstream registry, and return its body after deserializing it as json :param path: a full http path to retrieve that will be urljoin'd to the upstream registry url. :type path: basestring :return: whatever gets deserialized out of the response body's json """ url = urlparse.urljoin(self.registry_url, path) request = DownloadRequest(url, StringIO()) if path.endswith('/images'): # this is required by the docker index and indicates that it should # return an auth token if request.headers is None: request.headers = {} request.headers[self.DOCKER_TOKEN_HEADER] = 'true' report = self.downloader.download_one(request) if report.state == report.DOWNLOAD_FAILED: raise IOError(report.error_msg) self._parse_response_headers(report.headers) return json.loads(report.destination.getvalue())
def _get_single_path(self, path): """ Retrieve a single path within the upstream registry, and return its body after deserializing it as json :param path: a full http path to retrieve that will be urljoin'd to the upstream registry url. :type path: basestring :return: whatever gets deserialized out of the response body's json """ url = urlparse.urljoin(self.registry_url, path) request = DownloadRequest(url, StringIO()) if path.endswith('/images'): # this is required by the docker index and indicates that it should # return an auth token if request.headers is None: request.headers = {} request.headers[self.DOCKER_TOKEN_HEADER] = 'true' report = self.downloader.download_one(request) if report.state == report.DOWNLOAD_FAILED: raise IOError(report.error_msg) self._parse_response_headers(report.headers) return json.loads(report.destination.getvalue())
def _get_single_path(self, path): """ Retrieve a single path within the upstream registry, and return its body after deserializing it as json :param path: a full http path to retrieve that will be urljoin'd to the upstream registry url. :type path: basestring :return: whatever gets deserialized out of the response body's json """ # if talking to docker hub, we'll get an endpoint specified, and then we'll have to get # tags from that endpoint instead of talking to the original feed URL. if self.endpoint: # we assume the same scheme that the registry URL used registry_url_parts = urlparse.urlsplit(self.registry_url) parts = urlparse.SplitResult(scheme=registry_url_parts.scheme, netloc=self.endpoint, path=path, query=None, fragment=None) url = urlparse.urlunsplit(parts) else: url = urlparse.urljoin(self.registry_url, path) request = DownloadRequest(url, StringIO()) if path.endswith('/images'): # this is required by the docker index and indicates that it should # return an auth token if request.headers is None: request.headers = {} request.headers[self.DOCKER_TOKEN_HEADER] = 'true' # endpoints require auth if self.endpoint: self.add_auth_header(request) report = self.downloader.download_one(request) if report.state == report.DOWNLOAD_FAILED: raise IOError(report.error_msg) self._parse_response_headers(report.headers) return json.loads(report.destination.getvalue())
def _get_single_path(self, path): """ Retrieve a single path within the upstream registry, and return its body after deserializing it as json :param path: a full http path to retrieve that will be urljoin'd to the upstream registry url. :type path: basestring :return: whatever gets deserialized out of the response body's json """ # if talking to docker hub, we'll get an endpoint specified, and then we'll have to get # tags from that endpoint instead of talking to the original feed URL. if self.endpoint: # we assume the same scheme that the registry URL used registry_url_parts = urlparse.urlsplit(self.registry_url) parts = urlparse.SplitResult(scheme=registry_url_parts.scheme, netloc=self.endpoint, path=path, query=None, fragment=None) url = urlparse.urlunsplit(parts) else: url = urlparse.urljoin(self.registry_url, path) request = DownloadRequest(url, StringIO()) if path.endswith('/images'): # this is required by the docker index and indicates that it should # return an auth token if request.headers is None: request.headers = {} request.headers[self.DOCKER_TOKEN_HEADER] = 'true' # endpoints require auth if self.endpoint: self.add_auth_header(request) report = self.downloader.download_one(request) if report.state == report.DOWNLOAD_FAILED: raise IOError(report.error_msg) self._parse_response_headers(report.headers) return json.loads(report.destination.getvalue())