image-tool / backend /app /api /result.py
JunyoungK7's picture
Deploy to HF Spaces: Docker setup, CPU inference, env-gated config
a3953cb
Raw History Blame Contribute Delete
3.3 kB
"""
result.py — GET /result/{job_id}
Returns the full step history for a job plus backward-compatible top-level
status/image URL fields derived from the current step.
Response design
---------------
The response includes two layers:
1. Top-level fields (backward-compatible with the current frontend polling):
status — current step's status
result_image_url — current step's result image URL
original_image_url — step 0's original image URL (the uploaded file)
error_message — current step's error (if failed)
2. steps[] array (for the future multi-step navigation UI):
Each entry has step_number, status, original_image_url, result_image_url,
error_message. The frontend (next step) uses this to render a step
navigator.
URL derivation
--------------
Files live under STORAGE_DIR and are served at /storage/... by StaticFiles.
Path.relative_to(STORAGE_DIR).as_posix() extracts the relative path and
normalises Windows backslashes to forward slashes.
"""
from pathlib import Path
from fastapi import APIRouter, HTTPException
from app.config import STORAGE_DIR
from app.jobs_store import get_job
router = APIRouter()
def _to_url(abs_path: str | None) -> str | None:
"""Convert an absolute path under STORAGE_DIR to a /storage/… URL."""
if abs_path is None:
return None
try:
rel = Path(abs_path).relative_to(STORAGE_DIR)
return "/storage/" + rel.as_posix()
except ValueError:
return None
@router.get("/{job_id}")
def get_result(job_id: str) -> dict:
"""Return current job state including full step history.
The top-level status/result_image_url/original_image_url fields reflect
the current step, keeping existing frontend polling code working until
the multi-step UI is implemented.
"""
job = get_job(job_id)
if job is None:
raise HTTPException(status_code=404, detail=f"Job '{job_id}' not found.")
# Find current step record.
current = next(
(s for s in job.steps if s.step_number == job.current_step), None
)
# Step 0's original is the canonical "uploaded image" for before/after.
step0 = next((s for s in job.steps if s.step_number == 0), None)
# Build per-step summary for the history navigator.
steps_summary = [
{
"step_number": s.step_number,
"status": s.status,
"original_image_url": _to_url(s.original_image),
"result_image_url": _to_url(s.result_image),
"error_message": s.error_message,
}
for s in sorted(job.steps, key=lambda s: s.step_number)
]
return {
# Backward-compatible top-level fields (polled by existing frontend).
"job_id": job.id,
"current_step": job.current_step,
"status": current.status if current else "unknown",
"error_message": current.error_message if current else None,
"original_image_url": _to_url(step0.original_image) if step0 else None,
"result_image_url": _to_url(current.result_image) if current else None,
# Full history for the multi-step UI (used in the next frontend step).
"steps": steps_summary,
}