mirror of
https://github.com/enpaul/kodak.git
synced 2024-11-23 15:07:13 +00:00
Implement trivial functionality for image source endpoint
This commit is contained in:
parent
25b61a612c
commit
d5267e51d9
@ -31,6 +31,17 @@ class Checksum(NamedTuple):
|
||||
"""Construct from a hashlib object"""
|
||||
return cls(algorithm=data.name, digest=data.hexdigest())
|
||||
|
||||
def as_header(self) -> str:
|
||||
"""Format the checksum for the Content-Digest HTTP header"""
|
||||
if self.algorithm.startswith("sha"):
|
||||
alg = f"sha-{self.algorithm[3:]}"
|
||||
elif self.algorithm.startswith("id"):
|
||||
alg = f"id-sha-{self.algorithm[3:]}"
|
||||
else:
|
||||
alg = self.algorithm
|
||||
|
||||
return f"{alg}={self.digest}"
|
||||
|
||||
|
||||
class EnumField(peewee.CharField):
|
||||
"""Custom field for storing enums"""
|
||||
|
@ -38,7 +38,7 @@ class ImageRecord(KodakModel):
|
||||
hasher = hashlib.sha256()
|
||||
view = memoryview(bytearray(1024 * 1024))
|
||||
with path.open("rb", buffering=0) as infile:
|
||||
for chunk in iter(lambda: infile.readinto(view), 0):
|
||||
for chunk in iter(lambda: infile.readinto(view), 0): # type: ignore
|
||||
hasher.update(view[:chunk])
|
||||
|
||||
name = path.stem
|
||||
|
@ -1,3 +1,8 @@
|
||||
import datetime
|
||||
|
||||
import flask
|
||||
|
||||
from kodak import database
|
||||
from kodak.resources._shared import authenticated
|
||||
from kodak.resources._shared import KodakResource
|
||||
from kodak.resources._shared import ResponseTuple
|
||||
@ -9,9 +14,20 @@ class Image(KodakResource):
|
||||
routes = ("/image/<string:image_name>",)
|
||||
|
||||
@authenticated
|
||||
def get(self, image_name: str) -> ResponseTuple:
|
||||
def get(self, image_name: str) -> flask.Response: # pylint: disable=no-self-use
|
||||
"""Retrieve an original source image"""
|
||||
raise NotImplementedError
|
||||
with database.interface.atomic():
|
||||
image = database.ImageRecord.get(database.ImageRecord.name == image_name)
|
||||
|
||||
resp = flask.send_file(
|
||||
image.source,
|
||||
cache_timeout=int(datetime.timedelta(days=365).total_seconds()),
|
||||
add_etags=False,
|
||||
)
|
||||
|
||||
resp.headers["Content-Digest"] = image.checksum.as_header()
|
||||
|
||||
return resp
|
||||
|
||||
def head(self, image_name: str) -> ResponseTuple:
|
||||
"""Alias HEAD to GET"""
|
||||
|
@ -127,12 +127,12 @@ def build(config: Optional[configuration.KodakConfig] = None) -> None:
|
||||
|
||||
with database.interface.atomic():
|
||||
for image in database.ImageRecord.select().where(
|
||||
database.ImageRecord.deleted
|
||||
== False # pylint: disable=singleton-comparison
|
||||
database.ImageRecord.deleted # pylint: disable=singleton-comparison
|
||||
== False
|
||||
):
|
||||
if config.expose_source:
|
||||
logger.debug(f"Creating source link to {image.source}")
|
||||
image.create_link(config)
|
||||
else:
|
||||
logger.debug(f"Removing source link to {image.source}")
|
||||
image.delete_link(config)
|
||||
image.remove_link(config)
|
||||
|
Loading…
Reference in New Issue
Block a user