Fix: Use Next.js API proxy to avoid mixed-content/CORS errors
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 54s
CI / test-go-edu-search (push) Successful in 53s
CI / test-python-klausur (push) Failing after 2m57s
CI / test-python-agent-core (push) Successful in 43s
CI / test-nodejs-website (push) Successful in 46s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 54s
CI / test-go-edu-search (push) Successful in 53s
CI / test-python-klausur (push) Failing after 2m57s
CI / test-python-agent-core (push) Successful in 43s
CI / test-nodejs-website (push) Successful in 46s
HTTPS pages cannot fetch from HTTP backend ports. Added Next.js API route proxies for /api/vocabulary, /api/learning-units, /api/progress that forward to backend-lehrer internally (same Docker network, HTTP). All frontend pages now use same-origin requests (getApiBase = '') instead of direct port:8001 connections. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,11 +15,11 @@ interface QAItem {
|
||||
incorrect_count: number
|
||||
}
|
||||
|
||||
function getBackendUrl() {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8001'
|
||||
const { hostname, protocol } = window.location
|
||||
if (hostname === 'localhost') return 'http://localhost:8001'
|
||||
return `${protocol}//${hostname}:8001`
|
||||
function getApiBase() {
|
||||
return '' // Same-origin proxy
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default function FlashcardsPage() {
|
||||
@@ -45,7 +45,7 @@ export default function FlashcardsPage() {
|
||||
const loadQA = async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const resp = await fetch(`${getBackendUrl()}/api/learning-units/${unitId}/qa`)
|
||||
const resp = await fetch(`${getApiBase()}/api/learning-units/${unitId}/qa`)
|
||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
|
||||
const data = await resp.json()
|
||||
setItems(data.qa_items || [])
|
||||
@@ -63,7 +63,7 @@ export default function FlashcardsPage() {
|
||||
// Update Leitner progress
|
||||
try {
|
||||
await fetch(
|
||||
`${getBackendUrl()}/api/learning-units/${unitId}/leitner/update?item_id=${item.id}&correct=${correct}`,
|
||||
`${getApiBase()}/api/learning-units/${unitId}/leitner/update?item_id=${item.id}&correct=${correct}`,
|
||||
{ method: 'POST' }
|
||||
)
|
||||
} catch (err) {
|
||||
|
||||
@@ -13,11 +13,11 @@ interface MCQuestion {
|
||||
explanation?: string
|
||||
}
|
||||
|
||||
function getBackendUrl() {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8001'
|
||||
const { hostname, protocol } = window.location
|
||||
if (hostname === 'localhost') return 'http://localhost:8001'
|
||||
return `${protocol}//${hostname}:8001`
|
||||
function getApiBase() {
|
||||
return '' // Same-origin proxy
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default function QuizPage() {
|
||||
@@ -43,7 +43,7 @@ export default function QuizPage() {
|
||||
const loadMC = async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const resp = await fetch(`${getBackendUrl()}/api/learning-units/${unitId}/mc`)
|
||||
const resp = await fetch(`${getApiBase()}/api/learning-units/${unitId}/mc`)
|
||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
|
||||
const data = await resp.json()
|
||||
setQuestions(data.questions || [])
|
||||
|
||||
@@ -5,16 +5,16 @@ import { useParams, useRouter } from 'next/navigation'
|
||||
import { useTheme } from '@/lib/ThemeContext'
|
||||
import { AudioButton } from '@/components/learn/AudioButton'
|
||||
|
||||
function getBackendUrl() {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8001'
|
||||
const { hostname, protocol } = window.location
|
||||
if (hostname === 'localhost') return 'http://localhost:8001'
|
||||
return `${protocol}//${hostname}:8001`
|
||||
function getApiBase() {
|
||||
return '' // Same-origin proxy
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function getKlausurApiUrl() {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8086'
|
||||
const { hostname, protocol } = window.location
|
||||
|
||||
if (hostname === 'localhost') return 'http://localhost:8086'
|
||||
return `${protocol}//${hostname}/klausur-api`
|
||||
}
|
||||
@@ -39,7 +39,7 @@ export default function StoryPage() {
|
||||
|
||||
try {
|
||||
// First get the QA data to extract vocabulary
|
||||
const qaResp = await fetch(`${getBackendUrl()}/api/learning-units/${unitId}/qa`)
|
||||
const qaResp = await fetch(`${getApiBase()}/api/learning-units/${unitId}/qa`)
|
||||
let vocabulary: { english: string; german: string }[] = []
|
||||
|
||||
if (qaResp.ok) {
|
||||
@@ -58,7 +58,7 @@ export default function StoryPage() {
|
||||
}
|
||||
|
||||
// Generate story
|
||||
const resp = await fetch(`${getBackendUrl()}/api/learning-units/${unitId}/generate-story`, {
|
||||
const resp = await fetch(`${getApiBase()}/api/learning-units/${unitId}/generate-story`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ vocabulary, language, grade_level: '5-8' }),
|
||||
|
||||
@@ -13,11 +13,11 @@ interface QAItem {
|
||||
leitner_box: number
|
||||
}
|
||||
|
||||
function getBackendUrl() {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8001'
|
||||
const { hostname, protocol } = window.location
|
||||
if (hostname === 'localhost') return 'http://localhost:8001'
|
||||
return `${protocol}//${hostname}:8001`
|
||||
function getApiBase() {
|
||||
return '' // Same-origin proxy
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default function TypePage() {
|
||||
@@ -44,7 +44,7 @@ export default function TypePage() {
|
||||
const loadQA = async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const resp = await fetch(`${getBackendUrl()}/api/learning-units/${unitId}/qa`)
|
||||
const resp = await fetch(`${getApiBase()}/api/learning-units/${unitId}/qa`)
|
||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`)
|
||||
const data = await resp.json()
|
||||
setItems(data.qa_items || [])
|
||||
@@ -61,7 +61,7 @@ export default function TypePage() {
|
||||
|
||||
try {
|
||||
await fetch(
|
||||
`${getBackendUrl()}/api/learning-units/${unitId}/leitner/update?item_id=${item.id}&correct=${correct}`,
|
||||
`${getApiBase()}/api/learning-units/${unitId}/leitner/update?item_id=${item.id}&correct=${correct}`,
|
||||
{ method: 'POST' }
|
||||
)
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user