diff --git a/requirements.txt b/requirements.txt index ce5fbae..bcee37c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ anyio==3.7.1 beautifulsoup4==4.12.2 certifi==2023.7.22 charset-normalizer==3.2.0 +chevron==0.14.0 click==8.1.6 envyaml==1.10.211231 exceptiongroup==1.1.2 @@ -16,6 +17,7 @@ isodate==0.6.1 jstyleson==0.0.2 lxml==4.9.3 mf2py==1.1.3 +minio==7.1.17 pydantic==2.1.1 pydantic_core==2.4.0 pyparsing==3.1.1 diff --git a/src/config.yaml b/src/config.yaml index 8b13789..20ed304 100644 --- a/src/config.yaml +++ b/src/config.yaml @@ -1 +1,8 @@ - +images: + # This component will serve files from a static bucket, randomly + # You should set the bucket to public, we will return the url + access_key: ${ACCESS_KEY} + secret_key: ${SECRET_KEY} + endpoint: s3.clortox.com + bucket: static-assets + secure: True diff --git a/src/main.py b/src/main.py index 8f4a62c..9691259 100644 --- a/src/main.py +++ b/src/main.py @@ -1,8 +1,9 @@ from datetime import datetime, date from fastapi import FastAPI, HTTPException -from routers import recipe +from routers import recipe, images app = FastAPI() app.include_router(recipe.router) +app.include_router(images.router) diff --git a/src/routers/images.py b/src/routers/images.py new file mode 100644 index 0000000..cbacfa6 --- /dev/null +++ b/src/routers/images.py @@ -0,0 +1,62 @@ +from fastapi import APIRouter, Depends, HTTPException, Header + +from typing import List, Optional +from pydantic import BaseModel +import logging +from config import getConfig + +from minio import Minio +import random +import tempfile +import traceback + +router = APIRouter( + prefix="/images", + tags=["Images"], + responses={404: {"description": "Not found"}} + ) + +@router.get("/background/random") +async def background(accept: str = Header(None)): + """ + Will obtain a random image from the configured S3 bucket. + """ + endpoint = getConfig()["images.endpoint"] + access_key = getConfig()["images.access_key"] + secret_key = getConfig()["images.secret_key"] + bucket = getConfig()["images.bucket"] + secure = getConfig()["images.secure"] + + try: + client = Minio( + endpoint, + access_key=access_key, + secret_key=secret_key, + secure=secure + ) + + objects = client.list_objects(bucket) + object_names = [obj.object_name for obj in objects] + if not object_names: + raise HTTPException(status_code=500, detail="No data in bucket!") + + random_object_name = random.choice(object_names) + print(random_object_name) + scheme = "https" if secure else "http" + object_url = f"{scheme}://{endpoint}/{bucket}/{random_object_name}" + + + if accept and "image/" in accept: + with tempfile.NamedTemporaryFile(detel=True) as temp_file: + client.fget_object(bucket, random_object_name, temp_file) + return FileResponse(temp_file.name, headers={"Content-Disposition": f"attachment; filename={random_object_name}"}) + + return object_url + + + except Exception as err: + traceback.print_exc() + raise HTTPException(status_code=500, detail=f"Unknown error. Check logs {err}") + print(f"Error occurued processing background {err}") + +# TODO get a sync up background