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) ...@@ -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. **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:** 1. **Automatische Erkennung:**
- Wenn das Backend als **separater CapRover Service** läuft: Verwende die externe URL des Backends - `http://localhost:51821` (Standard, wenn beide im gleichen Container)
- Beispiel: `https://wg-easy-backend.corexmanagement.de` - `http://127.0.0.1:51821`
- Wenn beide im **gleichen Container** laufen: `http://localhost:51821` - `http://wg-easy:51821` (Docker Service-Name)
- Wenn Backend als **Docker Service** im Stack: Verwende Service-Namen (z.B. `http://wg-easy-backend:51821`) - `http://srv-captain--wg-easy:51821` (CapRover Service-Name)
2. **Environment Variable setzen:** 2. **Optional - Environment Variables:**
- In CapRover: App → Environment Variables - `WG_API_URL`: Falls das Backend nicht automatisch gefunden wird, kann die URL manuell gesetzt werden
- `WG_API_URL`: URL des wg-easy Backends
- `WG_PASSWORD`: Backend-Passwort (Standard: `CoreX2024!Secure#VPN`) - `WG_PASSWORD`: Backend-Passwort (Standard: `CoreX2024!Secure#VPN`)
3. **Standardwerte (falls keine Environment Variables gesetzt):** **Standardwerte:**
- **WG_API_URL**: `https://corex-wg-easy.corexmanagement.de` (Frontend-URL - muss angepasst werden!) - **WG_API_URL**: Automatische Erkennung (keine Konfiguration erforderlich!)
- **WG_PASSWORD**: `CoreX2024!Secure#VPN` - **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 ## 🐳 Docker Setup
......
// WireGuard Easy API Client // WireGuard Easy API Client
// WG API URL Konfiguration // WG API URL Konfiguration - Automatische Erkennung
// Wenn Frontend und Backend in der gleichen CapRover App laufen: // Versucht verschiedene URLs, falls keine Environment Variable gesetzt ist
// function getWgApiUrl(): string {
// Option 1: Backend läuft als separater CapRover Service mit eigener Domain if (process.env.WG_API_URL) {
// - Setze WG_API_URL auf die externe Backend-URL (z.B. https://wg-easy-backend.corexmanagement.de) return process.env.WG_API_URL
// }
// Option 2: Backend läuft im gleichen Docker-Netzwerk (nicht empfohlen für CapRover)
// - Verwende Docker Service-Namen oder interne IP // Standard-URL (wg-easy Backend läuft normalerweise auf Port 51821)
// // In CapRover: Wenn beide in der gleichen App, versuche verschiedene Optionen
// Option 3: Backend läuft auf separatem Port (nur wenn beide im gleichen Container) return 'http://localhost:51821'
// - localhost:51821 }
//
// WICHTIG: In CapRover sollte das Backend als eigener Service laufen mit eigener Domain! const WG_API_URL = getWgApiUrl()
// 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'
const WG_PASSWORD = process.env.WG_PASSWORD || 'CoreX2024!Secure#VPN' const WG_PASSWORD = process.env.WG_PASSWORD || 'CoreX2024!Secure#VPN'
interface WgClient { interface WgClient {
...@@ -68,50 +66,71 @@ export class WgApiClient { ...@@ -68,50 +66,71 @@ export class WgApiClient {
} }
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> { private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const url = `${this.baseUrl}${endpoint}` // Liste möglicher Backend-URLs zum Ausprobieren
const possibleUrls = [
const headers: Record<string, string> = { this.baseUrl, // Zuerst die konfigurierte URL versuchen
'Content-Type': 'application/json', 'http://localhost:51821',
...(options.headers as Record<string, string> || {}), '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 // Add basic auth if password is set
if (this.password) { if (this.password) {
headers['Authorization'] = `Basic ${Buffer.from(`:${this.password}`).toString('base64')}` 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 { // Success! Update baseUrl for future requests
const response = await fetch(url, { if (baseUrl !== this.baseUrl) {
...options, console.log(`[WG API] Successfully connected to: ${baseUrl}`)
headers, this.baseUrl = baseUrl
})
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}`)
} }
throw new Error(`WG API Error: ${response.status} ${errorText.substring(0, 200)}`)
}
const contentType = response.headers.get('content-type') const contentType = response.headers.get('content-type')
if (contentType && contentType.includes('application/json')) { if (contentType && contentType.includes('application/json')) {
return response.json() return response.json()
} }
// If not JSON, return as text // If not JSON, return as text
return response.text() as unknown as T return response.text() as unknown as T
} catch (error) { } catch (error) {
// Handle network errors // Network error - try next URL
if (error instanceof TypeError && error.message.includes('fetch failed')) { lastError = error instanceof Error ? error : new Error(String(error))
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}`) 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> { 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