fix: truncate scraped recipe slug to filesystem-safe length (#7862)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
TowyTowy
2026-07-17 20:37:19 +02:00
committed by GitHub
parent 31187b1a74
commit 95277e0e6b
2 changed files with 43 additions and 3 deletions

View File

@@ -4,13 +4,13 @@ from re import search as regex_search
from uuid import uuid4
from fastapi import HTTPException, status
from slugify import slugify
from mealie.core.root_logger import get_logger
from mealie.lang.providers import Translator
from mealie.pkgs import cache
from mealie.repos.repository_factory import AllRepositories
from mealie.schema.recipe import Recipe
from mealie.schema.recipe.recipe import create_recipe_slug
from mealie.services.recipe.recipe_data_service import RecipeDataService
from mealie.services.scraper.scraped_extras import ScrapedExtras
@@ -72,7 +72,7 @@ async def create_from_html(
if new_recipe.name is None:
new_recipe.name = "Untitled"
new_recipe.slug = slugify(new_recipe.name)
new_recipe.slug = create_recipe_slug(new_recipe.name)
new_recipe.image = cache.new_key(4)
except Exception as e:
recipe_data_service.logger.exception(f"Error Scraping Image: {e}")
@@ -80,6 +80,6 @@ async def create_from_html(
if new_recipe.name is None or new_recipe.name == "":
new_recipe.name = f"No Recipe Name Found - {uuid4()!s}"
new_recipe.slug = slugify(new_recipe.name)
new_recipe.slug = create_recipe_slug(new_recipe.name)
return new_recipe, extras

View File

@@ -0,0 +1,40 @@
import pytest
from mealie.lang.providers import get_locale_provider
from mealie.schema.recipe.recipe import Recipe
from mealie.services.scraper import scraper
from mealie.services.scraper.recipe_scraper import RecipeScraper
from mealie.services.scraper.scraped_extras import ScrapedExtras
@pytest.mark.asyncio
async def test_create_from_html_truncates_long_slug(monkeypatch):
"""A recipe scraped with an excessively long name must yield a slug short enough
to be used as a filesystem directory name.
Regression test for GH #7662: scraping (e.g. an Instagram caption) dumped the entire
text into the recipe name. The scraper used a raw ``slugify`` instead of the shared
``create_recipe_slug`` helper, so the persisted slug could exceed the OS 255-byte
filename limit. Editing/saving the recipe then raised an uncaught
``OSError: [Errno 36] File name too long`` in ``RecipeService.check_assets``.
"""
# ~1300 characters, mirroring the caption-as-title data from the bug report
long_name = "High Protein Low Calorie Recipes Smash Or Pass " * 28
async def fake_scrape(self, url, html=None, on_progress=None):
return Recipe(name=long_name), ScrapedExtras()
monkeypatch.setattr(RecipeScraper, "scrape", fake_scrape)
translator = get_locale_provider()
recipe, _ = await scraper.create_from_html(
"https://example.com/recipe",
repos=None, # type: ignore[arg-type]
translator=translator,
html="<html></html>",
)
# The full title is preserved (name column is unbounded)...
assert recipe.name == long_name
# ...but the slug is truncated to a filesystem-safe length.
assert 0 < len(recipe.slug) <= 250