from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from pathlib import Path import os import tempfile import logging from contextlib import asynccontextmanager from ocr_api.ocr_service import OCRService from ocr_api.mock_ocr_service import MockOCRService logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) ocr_service = None use_gpu = False @asynccontextmanager async def lifespan(app: FastAPI): global ocr_service try: ocr_service = OCRService(use_gpu=use_gpu, lang="en") logger.info("OCR Service initialized") except Exception as e: logger.warning(f"PaddleOCR failed, using mock: {e}") ocr_service = MockOCRService(use_gpu=False, lang="en") yield app = FastAPI( title="OCR API", version="1.0.0", lifespan=lifespan ) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) @app.get("/") def root(): return { "message": "OCR API running", "endpoints": { "health": "/health", "ocr": "/api/ocr" } } @app.get("/health") def health(): return {"status": "ok"} @app.post("/api/ocr") async def ocr(file: UploadFile = File(...)): if not ocr_service: raise HTTPException(503, "OCR not ready") ext = Path(file.filename).suffix.lower() if ext not in {".jpg", ".jpeg", ".png"}: raise HTTPException(400, "Unsupported file type") with tempfile.NamedTemporaryFile(delete=False, suffix=ext) as tmp: tmp.write(await file.read()) tmp_path = tmp.name try: result = ocr_service.process_image(tmp_path) return JSONResponse(result) finally: os.unlink(tmp_path)