mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-06-08 01:50:14 -04:00
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
from enum import StrEnum
|
|
|
|
from fastapi import APIRouter, HTTPException, status
|
|
from pydantic import UUID4
|
|
from starlette.responses import FileResponse
|
|
|
|
from mealie.schema.recipe import Recipe
|
|
from mealie.schema.recipe.recipe_timeline_events import RecipeTimelineEventOut
|
|
|
|
router = APIRouter(prefix="/recipes")
|
|
|
|
|
|
class ImageType(StrEnum):
|
|
original = "original.webp"
|
|
small = "min-original.webp"
|
|
tiny = "tiny-original.webp"
|
|
|
|
|
|
@router.get("/{recipe_id}/images/{file_name}")
|
|
async def get_recipe_img(recipe_id: UUID4, file_name: ImageType = ImageType.original):
|
|
"""
|
|
Takes in a recipe id, returns the static image. This route is proxied in the docker image
|
|
and should not hit the API in production
|
|
"""
|
|
recipe_image = Recipe.directory_from_id(recipe_id).joinpath("images", file_name.value)
|
|
|
|
if recipe_image.exists():
|
|
return FileResponse(recipe_image, media_type="image/webp")
|
|
else:
|
|
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
@router.get("/{recipe_id}/images/timeline/{timeline_event_id}/{file_name}")
|
|
async def get_recipe_timeline_event_img(
|
|
recipe_id: UUID4, timeline_event_id: UUID4, file_name: ImageType = ImageType.original
|
|
):
|
|
"""
|
|
Takes in a recipe id and event timeline id, returns the static image. This route is proxied in the docker image
|
|
and should not hit the API in production
|
|
"""
|
|
timeline_event_image = RecipeTimelineEventOut.image_dir_from_id(recipe_id, timeline_event_id).joinpath(
|
|
file_name.value
|
|
)
|
|
|
|
if timeline_event_image.exists():
|
|
return FileResponse(timeline_event_image, media_type="image/webp")
|
|
else:
|
|
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
@router.get("/{recipe_id}/assets/{file_name}")
|
|
async def get_recipe_asset(recipe_id: UUID4, file_name: str):
|
|
"""Returns a recipe asset"""
|
|
asset_dir = Recipe.directory_from_id(recipe_id).joinpath("assets")
|
|
file = asset_dir.joinpath(file_name).resolve()
|
|
|
|
if not file.is_relative_to(asset_dir.resolve()):
|
|
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
|
|
|
if file.exists():
|
|
# Force download and disable MIME sniffing so uploaded assets cannot be
|
|
# served as active content in Mealie's origin.
|
|
return FileResponse(
|
|
file,
|
|
filename=file.name,
|
|
content_disposition_type="attachment",
|
|
headers={"X-Content-Type-Options": "nosniff"},
|
|
)
|
|
else:
|
|
raise HTTPException(status.HTTP_404_NOT_FOUND)
|