feat(api): serve static files and update thumbnail paths
This commit is contained in:
@@ -302,6 +302,46 @@ class PromptManagerAPI:
|
||||
status=500,
|
||||
)
|
||||
|
||||
# Serve static files from web/lib directory
|
||||
@routes.get("/prompt_manager/lib/{filepath:.*}")
|
||||
async def serve_lib_static(request):
|
||||
"""Serve static library files (JS, CSS) from web/lib directory."""
|
||||
import os
|
||||
|
||||
# Explicit MIME type mapping
|
||||
MIME_TYPES = {
|
||||
".js": "application/javascript",
|
||||
".css": "text/css",
|
||||
".json": "application/json",
|
||||
".map": "application/json",
|
||||
}
|
||||
|
||||
filepath = request.match_info.get("filepath", "")
|
||||
|
||||
# Security: prevent directory traversal
|
||||
if ".." in filepath or filepath.startswith("/"):
|
||||
return web.Response(text="Forbidden", status=403)
|
||||
|
||||
current_dir = os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(__file__))
|
||||
)
|
||||
file_path = os.path.join(current_dir, "web", "lib", filepath)
|
||||
|
||||
if not os.path.exists(file_path) or not os.path.isfile(file_path):
|
||||
return web.Response(text=f"Not Found: {filepath}", status=404)
|
||||
|
||||
# Get extension and content type
|
||||
ext = os.path.splitext(file_path)[1].lower()
|
||||
content_type = MIME_TYPES.get(ext, "application/octet-stream")
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
content = f.read()
|
||||
|
||||
return web.Response(
|
||||
body=content,
|
||||
content_type=content_type,
|
||||
)
|
||||
|
||||
# Statistics endpoint
|
||||
@routes.get("/prompt_manager/stats")
|
||||
async def get_stats_route(request):
|
||||
@@ -1021,9 +1061,11 @@ class PromptManagerAPI:
|
||||
thumbnails_dir = output_path / "thumbnails"
|
||||
if thumbnails_dir.exists():
|
||||
thumbnail_ext = '.jpg' if is_video else extension
|
||||
thumbnail_rel_path = f"thumbnails/{media_path.stem}_thumb{thumbnail_ext}"
|
||||
# Preserve subdirectory structure in thumbnail path
|
||||
rel_path_no_ext = rel_path.with_suffix('')
|
||||
thumbnail_rel_path = f"thumbnails/{rel_path_no_ext.as_posix()}_thumb{thumbnail_ext}"
|
||||
thumbnail_abs_path = output_path / thumbnail_rel_path
|
||||
|
||||
|
||||
if thumbnail_abs_path.exists():
|
||||
thumbnail_url = f'/prompt_manager/images/serve/{Path(thumbnail_rel_path).as_posix()}'
|
||||
|
||||
@@ -1146,7 +1188,9 @@ class PromptManagerAPI:
|
||||
|
||||
# Also try to delete associated thumbnail if it exists
|
||||
try:
|
||||
thumbnail_path = output_path / "thumbnails" / f"{file_path.stem}_thumb{file_path.suffix}"
|
||||
rel_path = file_path.relative_to(output_path)
|
||||
rel_path_no_ext = rel_path.with_suffix('')
|
||||
thumbnail_path = output_path / "thumbnails" / f"{rel_path_no_ext.as_posix()}_thumb{file_path.suffix}"
|
||||
if thumbnail_path.exists():
|
||||
os.remove(thumbnail_path)
|
||||
self.logger.debug(f"Deleted associated thumbnail: {thumbnail_path}")
|
||||
@@ -1907,9 +1951,11 @@ class PromptManagerAPI:
|
||||
if thumbnails_dir.exists():
|
||||
# For videos, look for thumbnail with .jpg extension
|
||||
thumbnail_ext = '.jpg' if is_video else extension
|
||||
thumbnail_rel_path = f"thumbnails/{media_path.stem}_thumb{thumbnail_ext}"
|
||||
# Preserve subdirectory structure in thumbnail path
|
||||
rel_path_no_ext = rel_path.with_suffix('')
|
||||
thumbnail_rel_path = f"thumbnails/{rel_path_no_ext.as_posix()}_thumb{thumbnail_ext}"
|
||||
thumbnail_abs_path = output_path / thumbnail_rel_path
|
||||
|
||||
|
||||
if thumbnail_abs_path.exists():
|
||||
thumbnail_url = f'/prompt_manager/images/serve/{Path(thumbnail_rel_path).as_posix()}'
|
||||
|
||||
@@ -2159,10 +2205,12 @@ class PromptManagerAPI:
|
||||
is_video = any(media_file.name.lower().endswith(ext) for ext in video_extensions)
|
||||
|
||||
# For videos, always save thumbnail as .jpg
|
||||
# Preserve subdirectory structure in thumbnail path
|
||||
rel_path_no_ext = rel_path.with_suffix('')
|
||||
if is_video:
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path.stem}_thumb.jpg"
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path_no_ext.as_posix()}_thumb.jpg"
|
||||
else:
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path.stem}_thumb{rel_path.suffix}"
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path_no_ext.as_posix()}_thumb{rel_path.suffix}"
|
||||
|
||||
# Skip if thumbnail already exists and is newer than original
|
||||
if (thumbnail_path.exists() and
|
||||
@@ -2375,10 +2423,12 @@ class PromptManagerAPI:
|
||||
rel_path = media_file.relative_to(output_path)
|
||||
|
||||
# For videos, always save thumbnail as .jpg
|
||||
# Preserve subdirectory structure in thumbnail path
|
||||
rel_path_no_ext = rel_path.with_suffix('')
|
||||
if is_video:
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path.stem}_thumb.jpg"
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path_no_ext.as_posix()}_thumb.jpg"
|
||||
else:
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path.stem}_thumb{rel_path.suffix}"
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path_no_ext.as_posix()}_thumb{rel_path.suffix}"
|
||||
|
||||
# SAFETY: Ensure thumbnail path is within our thumbnails directory
|
||||
try:
|
||||
@@ -2994,7 +3044,27 @@ class PromptManagerAPI:
|
||||
'status': 'ok' if output_dirs else 'warning',
|
||||
'output_dirs': output_dirs
|
||||
}
|
||||
|
||||
|
||||
# Check image monitor status
|
||||
try:
|
||||
from ..utils.image_monitor import _monitor_instance
|
||||
if _monitor_instance is not None:
|
||||
monitor_status = _monitor_instance.get_status()
|
||||
results['image_monitor'] = {
|
||||
'status': 'ok' if monitor_status.get('observer_alive') else 'error',
|
||||
**monitor_status
|
||||
}
|
||||
else:
|
||||
results['image_monitor'] = {
|
||||
'status': 'error',
|
||||
'message': 'Image monitor not initialized'
|
||||
}
|
||||
except Exception as e:
|
||||
results['image_monitor'] = {
|
||||
'status': 'error',
|
||||
'message': f'Failed to get monitor status: {str(e)}'
|
||||
}
|
||||
|
||||
return web.json_response({
|
||||
'success': True,
|
||||
'diagnostics': results
|
||||
@@ -4739,9 +4809,11 @@ class PromptManagerAPI:
|
||||
thumbnail_url = None
|
||||
thumbnails_dir = output_path / "thumbnails"
|
||||
if thumbnails_dir.exists():
|
||||
thumbnail_path = thumbnails_dir / f"{image_path.stem}_thumb{image_path.suffix}"
|
||||
# Preserve subdirectory structure in thumbnail path
|
||||
rel_path_no_ext = rel_path.with_suffix('')
|
||||
thumbnail_path = thumbnails_dir / f"{rel_path_no_ext.as_posix()}_thumb{image_path.suffix}"
|
||||
if thumbnail_path.exists():
|
||||
thumbnail_url = f'/prompt_manager/images/serve/thumbnails/{image_path.stem}_thumb{image_path.suffix}'
|
||||
thumbnail_url = f'/prompt_manager/images/serve/thumbnails/{rel_path_no_ext.as_posix()}_thumb{image_path.suffix}'
|
||||
|
||||
images.append({
|
||||
'filename': image_path.name,
|
||||
|
||||
Reference in New Issue
Block a user