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:
@@ -22,11 +22,9 @@ interface VocabWord {
|
||||
tags: 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`
|
||||
/** Use Next.js API proxy to avoid mixed-content/CORS issues */
|
||||
function getApiBase() {
|
||||
return '' // Same-origin: /api/vocabulary/... proxied by Next.js
|
||||
}
|
||||
|
||||
export default function VocabularyPage() {
|
||||
@@ -55,7 +53,7 @@ export default function VocabularyPage() {
|
||||
|
||||
// Load filters on mount
|
||||
useEffect(() => {
|
||||
fetch(`${getBackendUrl()}/api/vocabulary/filters`)
|
||||
fetch(`${getApiBase()}/api/vocabulary/filters`)
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(d => { if (d) setFilters(d) })
|
||||
.catch(() => {})
|
||||
@@ -73,12 +71,12 @@ export default function VocabularyPage() {
|
||||
try {
|
||||
let url: string
|
||||
if (query.trim()) {
|
||||
url = `${getBackendUrl()}/api/vocabulary/search?q=${encodeURIComponent(query)}&limit=30`
|
||||
url = `${getApiBase()}/api/vocabulary/search?q=${encodeURIComponent(query)}&limit=30`
|
||||
} else {
|
||||
const params = new URLSearchParams({ limit: '30' })
|
||||
if (posFilter) params.set('pos', posFilter)
|
||||
if (diffFilter) params.set('difficulty', String(diffFilter))
|
||||
url = `${getBackendUrl()}/api/vocabulary/browse?${params}`
|
||||
url = `${getApiBase()}/api/vocabulary/browse?${params}`
|
||||
}
|
||||
const resp = await fetch(url)
|
||||
if (resp.ok) {
|
||||
@@ -107,7 +105,7 @@ export default function VocabularyPage() {
|
||||
if (!unitTitle.trim() || selectedWords.length === 0) return
|
||||
setIsCreating(true)
|
||||
try {
|
||||
const resp = await fetch(`${getBackendUrl()}/api/vocabulary/units`, {
|
||||
const resp = await fetch(`${getApiBase()}/api/vocabulary/units`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user