From 77cd608e596af94811c22a16ff58a265d9c7381e Mon Sep 17 00:00:00 2001 From: Ondrej Nosek Date: Fri, 31 Mar 2023 14:09:09 +0200 Subject: [PATCH 11/12] A HEAD query into a lookaside cache A query about whether some file is present in the lookaside cache was under authentication and it prevented using command `pre-push-check` for those without the 'packager' permission. Added another method (based on HTTP HEAD), that allows the same check without authentication. JIRA: RHELCMP-11485 Fixes: https://pagure.io/fedpkg/issue/513 Signed-off-by: Ondrej Nosek --- pyrpkg/__init__.py | 2 +- pyrpkg/lookaside.py | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py index 584c141..15203b7 100644 --- a/pyrpkg/__init__.py +++ b/pyrpkg/__init__.py @@ -4529,7 +4529,7 @@ class Commands(object): for entry in sourcesf.entries: filename = entry.file hash = entry.hash - file_exists_in_lookaside = self.lookasidecache.remote_file_exists( + file_exists_in_lookaside = self.lookasidecache.remote_file_exists_head( self.ns_repo_name if self.lookaside_namespaced else self.repo_name, filename, hash) diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py index 90f0f1e..ecbf12b 100644 --- a/pyrpkg/lookaside.py +++ b/pyrpkg/lookaside.py @@ -22,7 +22,7 @@ import sys import pycurl import six -from six.moves import http_client +from six.moves import http_client, urllib from .errors import (AlreadyUploadedError, DownloadError, InvalidHashType, UploadError) @@ -157,7 +157,7 @@ class CGILookasideCache(object): return self.log.info("Downloading %s", filename) - urled_file = filename.replace(' ', '%20') + urled_file = urllib.parse.quote(filename) url = self.get_download_url(name, urled_file, hash, hashtype, **kwargs) if isinstance(url, six.text_type): url = url.encode('utf-8') @@ -200,6 +200,38 @@ class CGILookasideCache(object): if not self.file_is_valid(outfile, hash, hashtype=hashtype): raise DownloadError('%s failed checksum' % filename) + def remote_file_exists_head(self, name, filename, hash): + """Verify whether a file exists on the lookaside cache. + Uses a HTTP HEAD request and doesn't require authentication. + + :param str name: The name of the module. (usually the name of the + SRPM). This can include the namespace as well (depending on what + the server side expects). + :param str filename: The name of the file to check for. + :param str hash: The known good hash of the file. + """ + + urled_file = urllib.parse.quote(filename) + url = self.get_download_url(name, urled_file, hash, self.hashtype) + + c = pycurl.Curl() + c.setopt(pycurl.URL, url) + c.setopt(pycurl.NOBODY, True) + c.setopt(pycurl.FOLLOWLOCATION, 1) + + try: + c.perform() + status = c.getinfo(pycurl.RESPONSE_CODE) + except Exception as e: + raise DownloadError(e) + finally: + c.close() + + if status != 200: + self.log.debug('Unavailable file \'%s\' at %s' % (filename, url)) + return False + return True + def remote_file_exists(self, name, filename, hash): """Verify whether a file exists on the lookaside cache -- 2.39.2