Files

90 lines
3.9 KiB
Python

"""Web API layer — wraps orchestrator with 202+ polling pattern."""
import uuid, json, 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
sys.path.insert(0, str(Path(__file__).parent.parent))
from config import Config
from orchestrator import run_pipeline
app = FastAPI(title="COBOL->Java Verify")
BASE = Path(__file__).parent
app.mount("/static", StaticFiles(directory=str(BASE / "static")), name="static")
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
@app.get("/", response_class=HTMLResponse)
async def index():
return (BASE / "templates" / "upload.html").read_text(encoding="utf-8")
@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")
(task_dir / name).write_bytes(content)
(TASKS_DIR / f"{task_id}.json").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"),"fields":data.get("fields",[])})
@app.get("/fields/{task_id}")
async def fields(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,"fields":data.get("fields",[]),
"debug":data.get("debug",{}),
"build_log":data.get("build_log","")})
@app.get("/result/{task_id}", response_class=HTMLResponse)
async def result(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())
html = (BASE / "templates" / "result.html").read_text(encoding="utf-8")
html = html.replace("{{ task.id }}", data.get("id", task_id))
if data.get("status") == "done" and data.get("result"):
r = data["result"]
html = html.replace("{{ task.status }}", "done")
html = html.replace("{{ task.result.status }}", r.get("status",""))
html = html.replace("{{ task.result.program }}", r.get("program",""))
html = html.replace("{{ task.result.matched }}", str(r.get("matched",0)))
html = html.replace("{{ task.result.mismatched }}", str(r.get("mismatched",0)))
html = html.replace("{{ task.result.runner }}", r.get("runner",""))
html = html.replace("{{ task.result.duration }}", str(r.get("duration",0)))
elif data.get("status") == "error":
html = html.replace("{{ task.status }}", "error")
html = html.replace("{{ task.result.status }}", data.get("result",""))
else:
html = html.replace("{{ task.status }}", data.get("status","queued"))
return HTMLResponse(html)