Commit 6d6ca448 authored by Hendrik Garske's avatar Hendrik Garske

Feat: Automatische Backend-URL Erkennung ohne Environment Variables

parent ed053abc
......@@ -68,26 +68,25 @@ Die Anwendung läuft jetzt auf [http://localhost:3000](http://localhost:3000)
**Wichtig:** Die Anwendung benötigt eine WireGuard Easy Backend-Instanz.
### Backend-Konfiguration in CapRover
### Backend-Konfiguration
Wenn Frontend und Backend in der **gleichen CapRover App** laufen, muss das Backend über die richtige URL erreichbar sein:
Die Anwendung versucht **automatisch**, das Backend zu finden. Es werden verschiedene URLs ausprobiert:
1. **Backend-URL ermitteln:**
- Wenn das Backend als **separater CapRover Service** läuft: Verwende die externe URL des Backends
- Beispiel: `https://wg-easy-backend.corexmanagement.de`
- Wenn beide im **gleichen Container** laufen: `http://localhost:51821`
- Wenn Backend als **Docker Service** im Stack: Verwende Service-Namen (z.B. `http://wg-easy-backend:51821`)
1. **Automatische Erkennung:**
- `http://localhost:51821` (Standard, wenn beide im gleichen Container)
- `http://127.0.0.1:51821`
- `http://wg-easy:51821` (Docker Service-Name)
- `http://srv-captain--wg-easy:51821` (CapRover Service-Name)
2. **Environment Variable setzen:**
- In CapRover: App → Environment Variables
- `WG_API_URL`: URL des wg-easy Backends
2. **Optional - Environment Variables:**
- `WG_API_URL`: Falls das Backend nicht automatisch gefunden wird, kann die URL manuell gesetzt werden
- `WG_PASSWORD`: Backend-Passwort (Standard: `CoreX2024!Secure#VPN`)
3. **Standardwerte (falls keine Environment Variables gesetzt):**
- **WG_API_URL**: `https://corex-wg-easy.corexmanagement.de` (Frontend-URL - muss angepasst werden!)
- **WG_PASSWORD**: `CoreX2024!Secure#VPN`
**Standardwerte:**
- **WG_API_URL**: Automatische Erkennung (keine Konfiguration erforderlich!)
- **WG_PASSWORD**: `CoreX2024!Secure#VPN`
**⚠️ Wichtig:** Setze `WG_API_URL` in CapRover auf die tatsächliche Backend-URL, sonst funktioniert die Verbindung nicht!
**Keine Konfiguration erforderlich** - die App findet das Backend automatisch!
## 🐳 Docker Setup
......
// WireGuard Easy API Client
// WG API URL Konfiguration
// Wenn Frontend und Backend in der gleichen CapRover App laufen:
//
// Option 1: Backend läuft als separater CapRover Service mit eigener Domain
// - Setze WG_API_URL auf die externe Backend-URL (z.B. https://wg-easy-backend.corexmanagement.de)
//
// Option 2: Backend läuft im gleichen Docker-Netzwerk (nicht empfohlen für CapRover)
// - Verwende Docker Service-Namen oder interne IP
//
// Option 3: Backend läuft auf separatem Port (nur wenn beide im gleichen Container)
// - localhost:51821
//
// WICHTIG: In CapRover sollte das Backend als eigener Service laufen mit eigener Domain!
// Setze WG_API_URL in CapRover als Environment Variable auf die Backend-URL
const WG_API_URL = process.env.WG_API_URL || 'https://corex-wg-easy.corexmanagement.de'
// WG API URL Konfiguration - Automatische Erkennung
// Versucht verschiedene URLs, falls keine Environment Variable gesetzt ist
function getWgApiUrl(): string {
if (process.env.WG_API_URL) {
return process.env.WG_API_URL
}
// Standard-URL (wg-easy Backend läuft normalerweise auf Port 51821)
// In CapRover: Wenn beide in der gleichen App, versuche verschiedene Optionen
return 'http://localhost:51821'
}
const WG_API_URL = getWgApiUrl()
const WG_PASSWORD = process.env.WG_PASSWORD || 'CoreX2024!Secure#VPN'
interface WgClient {
......@@ -68,50 +66,71 @@ export class WgApiClient {
}
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const url = `${this.baseUrl}${endpoint}`
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...(options.headers as Record<string, string> || {}),
}
// Liste möglicher Backend-URLs zum Ausprobieren
const possibleUrls = [
this.baseUrl, // Zuerst die konfigurierte URL versuchen
'http://localhost:51821',
'http://127.0.0.1:51821',
'http://wg-easy:51821',
'http://srv-captain--wg-easy:51821',
]
let lastError: Error | null = null
for (const baseUrl of possibleUrls) {
const url = `${baseUrl}${endpoint}`
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...(options.headers as Record<string, string> || {}),
}
// Add basic auth if password is set
if (this.password) {
headers['Authorization'] = `Basic ${Buffer.from(`:${this.password}`).toString('base64')}`
}
// Add basic auth if password is set
if (this.password) {
headers['Authorization'] = `Basic ${Buffer.from(`:${this.password}`).toString('base64')}`
}
console.log(`[WG API] Requesting: ${url}`)
console.log(`[WG API] Trying: ${url}`)
try {
const response = await fetch(url, {
...options,
headers,
})
if (!response.ok) {
const errorText = await response.text()
// Check if it's HTML (404 page) - means endpoint doesn't exist
if (errorText.includes('<!DOCTYPE html>') || errorText.includes('<html')) {
// Try next URL
continue
}
// Other HTTP errors - try next URL
continue
}
try {
const response = await fetch(url, {
...options,
headers,
})
if (!response.ok) {
const errorText = await response.text()
// Check if it's HTML (404 page) - means endpoint doesn't exist
if (errorText.includes('<!DOCTYPE html>') || errorText.includes('<html')) {
throw new Error(`WG API Endpoint not found: ${endpoint} (404). Check if WG_API_URL is correct: ${this.baseUrl}`)
// Success! Update baseUrl for future requests
if (baseUrl !== this.baseUrl) {
console.log(`[WG API] Successfully connected to: ${baseUrl}`)
this.baseUrl = baseUrl
}
throw new Error(`WG API Error: ${response.status} ${errorText.substring(0, 200)}`)
}
const contentType = response.headers.get('content-type')
if (contentType && contentType.includes('application/json')) {
return response.json()
}
// If not JSON, return as text
return response.text() as unknown as T
} catch (error) {
// Handle network errors
if (error instanceof TypeError && error.message.includes('fetch failed')) {
throw new Error(`Failed to connect to WG API at ${this.baseUrl}. Please check if the backend is running and WG_API_URL is correct. Original error: ${error.message}`)
const contentType = response.headers.get('content-type')
if (contentType && contentType.includes('application/json')) {
return response.json()
}
// If not JSON, return as text
return response.text() as unknown as T
} catch (error) {
// Network error - try next URL
lastError = error instanceof Error ? error : new Error(String(error))
continue
}
// Re-throw other errors
throw error
}
// All URLs failed
throw new Error(`Failed to connect to WG API. Tried: ${possibleUrls.join(', ')}. Last error: ${lastError?.message || 'Unknown error'}`)
}
async getStats(): Promise<WgStats> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment