Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/youtube_extension/backend/api/advanced_video_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ async def analyze_segment(request: TemporalSegmentRequest):
}
except Exception as e:
logger.error(f"Segment analysis failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


@router.post("/temporal/events")
Expand Down Expand Up @@ -211,7 +211,7 @@ async def extract_temporal_events(request: TemporalEventsRequest):
}
except Exception as e:
logger.error(f"Event extraction failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


@router.post("/temporal/question")
Expand Down Expand Up @@ -244,7 +244,7 @@ async def answer_temporal_question(request: TemporalQuestionRequest):
}
except Exception as e:
logger.error(f"Temporal question failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


@router.post("/temporal/timeline")
Expand Down Expand Up @@ -285,7 +285,7 @@ async def create_timeline(request: TimelineRequest):
raise
except Exception as e:
logger.error(f"Timeline creation failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


@router.post("/temporal/compare-segments")
Expand Down Expand Up @@ -319,7 +319,7 @@ async def compare_segments(request: SegmentComparisonRequest):
}
except Exception as e:
logger.error(f"Segment comparison failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


@router.post("/temporal/tutorial-steps")
Expand Down Expand Up @@ -347,7 +347,7 @@ async def extract_tutorial_steps(request: TutorialStepsRequest):
}
except Exception as e:
logger.error(f"Tutorial extraction failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


# ============ Structured Output Endpoint ============
Expand Down Expand Up @@ -435,7 +435,7 @@ async def analyze_with_schema(request: StructuredAnalysisRequest):
}
except Exception as e:
logger.error(f"Structured analysis failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")


# ============ CloudEvents Publishing Endpoint ============
Expand Down Expand Up @@ -488,4 +488,4 @@ async def publish_video_event(
}
except Exception as e:
logger.error(f"Event publishing failed: {e}", exc_info=True)
raise HTTPException(500, str(e))
raise HTTPException(status_code=500, detail="Internal server error")
13 changes: 6 additions & 7 deletions src/youtube_extension/backend/cloud_ai_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,17 +256,18 @@ async def analyze_video(request: VideoAnalysisRequest):
return format_analysis_result(result)

except RateLimitError as e:
# RateLimitError/ConfigurationError subclass CloudAIError, so they must be
# caught BEFORE the base handler or they are dead code (returning the
# dynamic 503 and leaking config detail — CWE-209).
# Must precede CloudAIError: RateLimitError subclasses it, so catching
# the base first would shadow this handler and return a 503 instead.
logger.warning(f"Rate limit exceeded: {e}")
raise HTTPException(status_code=429, detail=f"Rate limit exceeded: {str(e)}")
except ConfigurationError as e:
# Must precede CloudAIError (same subclassing reason) so configuration
# failures reach this sanitized 500 rather than the dynamic 503 below.
logger.error(f"Configuration error: {e}", exc_info=True)
raise HTTPException(status_code=500, detail="Internal server error")
except CloudAIError as e:
logger.error(f"Cloud AI analysis failed: {e}")
raise HTTPException(status_code=503, detail=f"AI analysis failed: {str(e)}")
logger.error(f"Cloud AI analysis failed: {e}", exc_info=True)
raise HTTPException(status_code=503, detail="AI service temporarily unavailable. Please retry in a few moments.")
except HTTPException:
raise
except Exception as e:
Expand Down Expand Up @@ -327,8 +328,6 @@ async def analyze_video_multi_provider(request: VideoAnalysisRequest):
return formatted_results

except HTTPException:
# parse_analysis_types() raises HTTPException(400, ...); preserve the 4xx
# contract instead of collapsing it into a 500 (matches the other handlers).
raise
except Exception as e:
logger.error(f"Multi-provider analysis failed: {e}", exc_info=True)
Expand Down
15 changes: 7 additions & 8 deletions src/youtube_extension/backend/cloud_api_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ async def process_video_cloud(
)

except Exception as e:
# Exception text is logged server-side only; never returned to the client.
logger.error(f"Cloud processing failed: {e}", exc_info=True)
error_msg = f"Cloud processing failed: {str(e)}"
logger.error(error_msg, exc_info=True)

# detail is a static string; error_msg (with the exception) is logged above only
raise HTTPException(status_code=500, detail="Internal server error")

@router.post("/api/v3/process-video-task")
Expand Down Expand Up @@ -206,21 +208,18 @@ async def process_video_task_handler(
}

except Exception as e:
# Exception text is logged server-side only. It must NOT be persisted to
# task state: get_video_status / get_video_result echo error_message back
# to clients, so a raw str(e) there would re-expose internal detail (CWE-209).
logger.error(f"Task processing failed: {e}", exc_info=True)

# Update state with a user-safe message
# Update state with a static error message; raw exception is logged above only
try:
firestore_service = await get_firestore_service()
await firestore_service.update_state(
payload.video_id,
status='failed',
error_message="Internal server error"
error_message="Task processing failed"
)
except Exception as state_error:
logger.error(f"Failed to update error state: {state_error}", exc_info=True)
logger.error(f"Failed to update error state: {state_error}")

raise HTTPException(status_code=500, detail="Internal server error")

Expand Down
Loading
Loading