From 7bd7d0f79359c7c07408b75dd9e358fb74b78f19 Mon Sep 17 00:00:00 2001 From: Pier-Jean Malandrino Date: Fri, 3 Apr 2026 13:50:32 +0200 Subject: [PATCH] Validate page bounds on preview endpoint Reject requests where page exceeds the document page count with a clear 400 error, instead of letting pdf2image fail with an opaque exception. --- document-parser/api/documents.py | 6 ++++++ document-parser/tests/test_api_endpoints.py | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/document-parser/api/documents.py b/document-parser/api/documents.py index 88a4d1f..8fac0bb 100644 --- a/document-parser/api/documents.py +++ b/document-parser/api/documents.py @@ -84,6 +84,12 @@ async def preview( if not doc: raise HTTPException(status_code=404, detail="Document not found") + if doc.page_count and page > doc.page_count: + raise HTTPException( + status_code=400, + detail=f"Page {page} out of range (document has {doc.page_count} pages)", + ) + try: with open(doc.storage_path, "rb") as f: file_content = f.read() diff --git a/document-parser/tests/test_api_endpoints.py b/document-parser/tests/test_api_endpoints.py index 30b890c..f185da4 100644 --- a/document-parser/tests/test_api_endpoints.py +++ b/document-parser/tests/test_api_endpoints.py @@ -104,6 +104,19 @@ class TestDocumentEndpoints: ) assert resp.status_code == 413 + @patch("services.document_service.find_by_id", new_callable=AsyncMock) + def test_preview_page_out_of_range(self, mock_find, client): + mock_find.return_value = Document( + id="d1", + filename="test.pdf", + page_count=3, + storage_path="/tmp/test.pdf", + ) + + resp = client.get("/api/documents/d1/preview?page=10") + assert resp.status_code == 400 + assert "out of range" in resp.json()["detail"] + @patch("services.document_service.delete", new_callable=AsyncMock) def test_delete_document(self, mock_delete, client): mock_delete.return_value = True