]> git.ipfire.org Git - pbs.git/commitdiff
mirrors: Support HEAD requests in load balancer
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 11 Feb 2025 15:43:29 +0000 (15:43 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 11 Feb 2025 16:03:08 +0000 (16:03 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/__init__.py
src/web/mirrors.py

index ee9a2a30427130bf8b0588a23da255e6fc1b7492..24bc179d103d4509b8d460e3dba6a42316b62f35 100644 (file)
@@ -9,6 +9,7 @@ import logging
 import os
 import shutil
 import ssl
+import stat
 import systemd.journal
 import tempfile
 import urllib.parse
@@ -363,6 +364,26 @@ class Backend(object):
 
                return os.path.exists(path)
 
+       @run_in_thread
+       def stat(self, path, fmt=None):
+               """
+                       stat()s a file
+               """
+               # Make the path absolute
+               if not path.startswith("/"):
+                       path = self.path(path)
+
+               # Stat the file
+               s = os.stat(path)
+
+               # Check if the format matches
+               if fmt:
+                       # Return nothing if the format does not match
+                       if not stat.S_IFMT(s.st_mode) == fmt:
+                               return
+
+               return s
+
        @run_in_thread
        def makedirs(self, path, **kwargs):
                """
index ff036414318366a85729d20d8de6f85ff03fc632..b16c1d35e9e07367f53fcb3fbc5817fdf96cdcb4 100644 (file)
@@ -1,6 +1,8 @@
 #!/usr/bin/python
 
+import datetime
 import logging
+import stat
 import tornado.web
 
 from . import base
@@ -140,7 +142,7 @@ class DownloadsHandler(base.BaseHandler):
        @base.ratelimit(limit=100, minutes=60, key="downloads")
        async def get(self, path):
                # Check if the file exists
-               if not await self.backend.exists(path):
+               if not await self.backend.stat(path, stat.S_IFREG):
                        raise tornado.web.HTTPError(404)
 
                # Fetch all mirrors for this client
@@ -168,6 +170,20 @@ class DownloadsHandler(base.BaseHandler):
 
                self.redirect(url)
 
+       @base.ratelimit(limit=100, minutes=60, key="downloads")
+       async def head(self, path):
+               # Stat the file
+               s = await self.backend.stat(path, stat.S_IFREG)
+
+               # Send 404 if the file does not exist
+               if not s:
+                       raise tornado.web.HTTPError(404)
+
+               # Send a couple of headers
+               self.set_header("Content-Type", "application/octet-stream")
+               self.set_header("Content-Length", s.st_size)
+               self.set_header("Last-Modified", datetime.datetime.fromtimestamp(s.st_mtime))
+
        async def write_error(self, *args, **kwargs):
                """
                        Don't send any body in error responses