-
Notifications
You must be signed in to change notification settings - Fork 0
fix: validate BACKEND_URL before using it #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,7 +14,10 @@ function getGemini() { | |||||||||||||||||||||||||||||||||||||||
| return _gemini; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'; | ||||||||||||||||||||||||||||||||||||||||
| // Backend URL with validation - skip if not a valid URL | ||||||||||||||||||||||||||||||||||||||||
| const rawBackendUrl = process.env.BACKEND_URL || ''; | ||||||||||||||||||||||||||||||||||||||||
| const BACKEND_URL = rawBackendUrl.startsWith('http') ? rawBackendUrl : 'http://localhost:8000'; | ||||||||||||||||||||||||||||||||||||||||
| const BACKEND_AVAILABLE = rawBackendUrl.startsWith('http'); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
21
|
||||||||||||||||||||||||||||||||||||||||
| const BACKEND_URL = rawBackendUrl.startsWith('http') ? rawBackendUrl : 'http://localhost:8000'; | |
| const BACKEND_AVAILABLE = rawBackendUrl.startsWith('http'); | |
| let BACKEND_URL = 'http://localhost:8000'; | |
| let BACKEND_AVAILABLE = false; | |
| if (rawBackendUrl) { | |
| try { | |
| const parsed = new URL(rawBackendUrl); | |
| const protocolOk = parsed.protocol === 'http:' || parsed.protocol === 'https:'; | |
| const hasTemplateTokens = rawBackendUrl.includes('${'); | |
| if (protocolOk && !hasTemplateTokens) { | |
| BACKEND_URL = rawBackendUrl; | |
| BACKEND_AVAILABLE = true; | |
| } | |
| } catch { | |
| // Invalid BACKEND_URL; keep defaults | |
| } | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,9 @@ | ||||||||||||||||||||||||||||||||||||||||
| import { NextResponse } from 'next/server'; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'; | ||||||||||||||||||||||||||||||||||||||||
| // Backend URL with validation - skip if not a valid URL | ||||||||||||||||||||||||||||||||||||||||
| const rawBackendUrl = process.env.BACKEND_URL || ''; | ||||||||||||||||||||||||||||||||||||||||
| const BACKEND_URL = rawBackendUrl.startsWith('http') ? rawBackendUrl : 'http://localhost:8000'; | ||||||||||||||||||||||||||||||||||||||||
| const BACKEND_AVAILABLE = rawBackendUrl.startsWith('http'); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
7
|
||||||||||||||||||||||||||||||||||||||||
| const BACKEND_URL = rawBackendUrl.startsWith('http') ? rawBackendUrl : 'http://localhost:8000'; | |
| const BACKEND_AVAILABLE = rawBackendUrl.startsWith('http'); | |
| let BACKEND_URL = 'http://localhost:8000'; | |
| let BACKEND_AVAILABLE = false; | |
| if (rawBackendUrl) { | |
| try { | |
| const parsed = new URL(rawBackendUrl); | |
| const isHttpProtocol = parsed.protocol === 'http:' || parsed.protocol === 'https:'; | |
| const hasPlaceholder = rawBackendUrl.includes('${'); | |
| if (isHttpProtocol && !hasPlaceholder) { | |
| BACKEND_URL = rawBackendUrl; | |
| BACKEND_AVAILABLE = true; | |
| } | |
| } catch { | |
| // Invalid URL in BACKEND_URL; fall back to defaults | |
| } | |
| } |
Copilot
AI
Feb 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In GET, if BACKEND_AVAILABLE is true but the backend health check fails, the handler currently falls through to the frontend-only response with backend_status: 'not-configured', which misrepresents the state (it is configured but unreachable). Consider returning backend_status: 'unavailable' (or similar) when the fetch throws, and reserving 'not-configured' strictly for when BACKEND_AVAILABLE is false.
| // Backend configured but unreachable | |
| // Backend configured but unreachable | |
| return NextResponse.json({ | |
| name: 'UVAI Video Analysis API', | |
| version: '2.0.0', | |
| backend_status: 'unavailable', | |
| frontend_pipeline: 'active', | |
| endpoints: { | |
| analyze: 'POST /api/video - Analyze a video URL', | |
| health: 'GET /api/video - Check API status', | |
| }, | |
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: The new
BACKEND_AVAILABLEflag isfalsewhenprocess.env.BACKEND_URLis unset, which disables the documented localhost fallback and breaks local development workflows.Severity: MEDIUM
Suggested Fix
The logic should differentiate between an unset environment variable and an invalid one. A potential fix is to set
BACKEND_AVAILABLEtotrueifrawBackendUrlis empty, allowing the localhost fallback to be used. For example:const BACKEND_AVAILABLE = rawBackendUrl.startsWith('http') || rawBackendUrl === '';. This preserves the original fallback behavior for local development while still guarding against invalid template strings from deployment environments.Prompt for AI Agent
Did we get this right? 👍 / 👎 to inform future reviews.