diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 39996f8..57cf054 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -17,9 +17,10 @@ services: - GEMINI_API_KEY=${GEMINI_API_KEY:-} - GEMINI_MODEL=${GEMINI_MODEL:-gemini-2.5-flash} - GEMINI_TIMEOUT_MS=${GEMINI_TIMEOUT_MS:-20000} - # adapter-node-Default ist 512 KB; Rezept-Fotos koennen bis 8 MB sein. - # Multipart-Overhead einrechnen -> 10 MB gibt etwas Puffer. - - BODY_SIZE_LIMIT=10000000 + # adapter-node-Default ist 512 KB. Tablet- und iPad-Pro-Kameras liefern + # JPEGs/HEICs bis 15 MB. Endpoint-Limit ist 20 MB; hier 25 MB fuer den + # Multipart-Overhead. + - BODY_SIZE_LIMIT=25000000 depends_on: - searxng restart: unless-stopped diff --git a/src/routes/api/recipes/extract-from-photo/+server.ts b/src/routes/api/recipes/extract-from-photo/+server.ts index cc8da10..927b1ac 100644 --- a/src/routes/api/recipes/extract-from-photo/+server.ts +++ b/src/routes/api/recipes/extract-from-photo/+server.ts @@ -6,7 +6,11 @@ import { pickRandomPhrase } from '$lib/server/ai/description-phrases'; import { createRateLimiter } from '$lib/server/ai/rate-limit'; import type { Ingredient, Step } from '$lib/types'; -const MAX_BYTES = 8 * 1024 * 1024; +// 20 MB deckt auch Tablet- und iPad-Pro-Fotos ab (oft 10-15 MB JPEG/HEIC). +// Muss zusammen mit BODY_SIZE_LIMIT (docker-compose.prod.yml) hochgezogen werden -- +// SvelteKit rejected groessere Bodies frueher und wirft dann undurchsichtige +// "Multipart erwartet"-Fehler. +const MAX_BYTES = 20 * 1024 * 1024; const ALLOWED_MIME = new Set([ 'image/jpeg', 'image/png', diff --git a/tests/integration/extract-from-photo.test.ts b/tests/integration/extract-from-photo.test.ts index 68c0388..ed9a137 100644 --- a/tests/integration/extract-from-photo.test.ts +++ b/tests/integration/extract-from-photo.test.ts @@ -70,8 +70,8 @@ describe('POST /api/recipes/extract-from-photo', () => { expect(body.recipe.id).toBeNull(); }); - it('413 when file exceeds 8 MB', async () => { - const big = Buffer.alloc(9 * 1024 * 1024); + it('413 when file exceeds 20 MB', async () => { + const big = Buffer.alloc(21 * 1024 * 1024); const fd = new FormData(); fd.append('photo', new Blob([new Uint8Array(big)], { type: 'image/jpeg' })); // eslint-disable-next-line @typescript-eslint/no-explicit-any