"""Web API layer — wraps orchestrator with 202+ polling pattern.""" import uuid, json, shutil, sys, os from pathlib import Path from datetime import datetime from fastapi import FastAPI, UploadFile, File, Form, HTTPException from fastapi.responses import HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from starlette.requests import Request sys.path.insert(0, str(Path(__file__).parent.parent)) from config import Config from orchestrator import run_pipeline app = FastAPI(title="COBOL→Java Verify") app.mount("/static", StaticFiles(directory=str(Path(__file__).parent / "static")), name="static") templates = Jinja2Templates(directory=str(Path(__file__).parent / "templates")) TASKS_DIR = Path("tasks") TASKS_DIR.mkdir(exist_ok=True) UPLOAD_DIR = Path("uploads") UPLOAD_DIR.mkdir(exist_ok=True) MAX_SIZE = 10 * 1024 * 1024 # 10MB @app.get("/", response_class=HTMLResponse) async def index(request: Request): return templates.TemplateResponse("upload.html", {"request": request}) @app.post("/verify") async def verify( copybook: UploadFile = File(...), cobol_src: UploadFile = File(...), java_src: UploadFile = File(...), mapping: UploadFile = File(...), runner: str = Form("native"), ): task_id = str(uuid.uuid4())[:8] task_dir = UPLOAD_DIR / task_id task_dir.mkdir(parents=True, exist_ok=True) for f, name in [(copybook, "copybook.cpy"), (cobol_src, "program.cbl"), (java_src, "java"), (mapping, "mapping.yaml")]: content = await f.read() if len(content) > MAX_SIZE: raise HTTPException(413, f"{f.filename} exceeds 10MB limit") dest = task_dir / name dest.write_bytes(content) task_file = TASKS_DIR / f"{task_id}.json" task_file.write_text(json.dumps({ "id": task_id, "status": "queued", "copybook": str(task_dir / "copybook.cpy"), "cobol_src": str(task_dir / "program.cbl"), "java_src": str(task_dir / "java"), "mapping": str(task_dir / "mapping.yaml"), "runner": runner, "created": datetime.now().isoformat() })) return JSONResponse({"task_id": task_id, "status": "queued"}, status_code=202) @app.get("/status/{task_id}") async def status(task_id: str): tf = TASKS_DIR / f"{task_id}.json" if not tf.exists(): raise HTTPException(404, "task not found") data = json.loads(tf.read_text()) return JSONResponse({"task_id": task_id, "status": data.get("status", "unknown"), "result": data.get("result")}) @app.get("/result/{task_id}", response_class=HTMLResponse) async def result(request: Request, task_id: str): tf = TASKS_DIR / f"{task_id}.json" if not tf.exists(): raise HTTPException(404, "task not found") data = json.loads(tf.read_text()) return templates.TemplateResponse("result.html", {"request": request, "task": data})