175 lines
5.6 KiB
JavaScript
175 lines
5.6 KiB
JavaScript
/**
|
|
* Lokaler Reverse Proxy für PTV Geocoding API
|
|
* Umgeht CORS-Probleme bei der Entwicklung
|
|
*/
|
|
|
|
const http = require('http');
|
|
const https = require('https');
|
|
const url = require('url');
|
|
|
|
const PORT = 3000;
|
|
const PTV_API_BASE = 'https://api.myptv.com';
|
|
|
|
// CORS Headers für alle Responses
|
|
const corsHeaders = {
|
|
'Access-Control-Allow-Origin': '*',
|
|
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
'Content-Type': 'application/json',
|
|
};
|
|
|
|
const server = http.createServer((req, res) => {
|
|
console.log(`📨 ${req.method} ${req.url}`);
|
|
|
|
// Health check endpoint
|
|
if (req.url === '/health') {
|
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
res.end('healthy');
|
|
return;
|
|
}
|
|
|
|
// Handle preflight requests
|
|
if (req.method === 'OPTIONS') {
|
|
res.writeHead(200, corsHeaders);
|
|
res.end();
|
|
return;
|
|
}
|
|
|
|
// Nur GET Requests erlauben
|
|
if (req.method !== 'GET') {
|
|
res.writeHead(405, corsHeaders);
|
|
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
|
return;
|
|
}
|
|
|
|
// Parse URL
|
|
const parsedUrl = url.parse(req.url, true);
|
|
const { lat, lon, apiKey } = parsedUrl.query;
|
|
|
|
// Validierung
|
|
if (!lat || !lon || !apiKey) {
|
|
res.writeHead(400, corsHeaders);
|
|
res.end(JSON.stringify({
|
|
error: 'Missing parameters: lat, lon, apiKey are required',
|
|
}));
|
|
return;
|
|
}
|
|
|
|
// PTV API URL erstellen
|
|
const ptvUrl = `${PTV_API_BASE}/geocoding/v1/locations/by-position/${lat}/${lon}?language=de&apiKey=${apiKey}`;
|
|
|
|
console.log(`🔄 Weiterleitung an: ${ptvUrl.replace(apiKey, 'API_KEY_HIDDEN')}`);
|
|
|
|
// Request an PTV API
|
|
https.get(ptvUrl, (ptvRes) => {
|
|
let data = '';
|
|
|
|
ptvRes.on('data', (chunk) => {
|
|
data += chunk;
|
|
});
|
|
|
|
ptvRes.on('end', () => {
|
|
try {
|
|
const jsonData = JSON.parse(data);
|
|
|
|
// Erfolgreiche Response
|
|
if (ptvRes.statusCode === 200) {
|
|
console.log('✅ PTV API Response erfolgreich');
|
|
|
|
// Adresse extrahieren
|
|
if (jsonData.locations && jsonData.locations.length > 0) {
|
|
const location = jsonData.locations[0];
|
|
if (location.address) {
|
|
const address = location.address;
|
|
const street = address.street || '';
|
|
const houseNumber = address.houseNumber || '';
|
|
const postalCode = address.postalCode || '';
|
|
const city = address.city || '';
|
|
|
|
const formattedAddress = `${street} ${houseNumber}, ${postalCode} ${city}`.trim();
|
|
|
|
const response = {
|
|
success: true,
|
|
location: formattedAddress,
|
|
coordinates: {
|
|
lat: parseFloat(lat),
|
|
lon: parseFloat(lon),
|
|
},
|
|
rawData: location,
|
|
};
|
|
|
|
console.log(`📍 Adresse: ${formattedAddress}`);
|
|
res.writeHead(200, corsHeaders);
|
|
res.end(JSON.stringify(response));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Fallback auf Koordinaten
|
|
const response = {
|
|
success: true,
|
|
location: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
|
|
coordinates: {
|
|
lat: parseFloat(lat),
|
|
lon: parseFloat(lon),
|
|
},
|
|
};
|
|
|
|
res.writeHead(200, corsHeaders);
|
|
res.end(JSON.stringify(response));
|
|
} else {
|
|
// Fehler von PTV API
|
|
console.log(`❌ PTV API Fehler: ${ptvRes.statusCode}`);
|
|
res.writeHead(ptvRes.statusCode, corsHeaders);
|
|
res.end(JSON.stringify({
|
|
success: false,
|
|
error: `PTV API Error: ${ptvRes.statusCode}`,
|
|
fallbackLocation: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ JSON Parse Fehler:', error.message);
|
|
res.writeHead(500, corsHeaders);
|
|
res.end(JSON.stringify({
|
|
success: false,
|
|
error: 'Failed to parse PTV API response',
|
|
fallbackLocation: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
|
|
}));
|
|
}
|
|
});
|
|
}).on('error', (error) => {
|
|
console.error('❌ Request Fehler:', error.message);
|
|
res.writeHead(500, corsHeaders);
|
|
res.end(JSON.stringify({
|
|
success: false,
|
|
error: error.message,
|
|
fallbackLocation: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
|
|
}));
|
|
});
|
|
});
|
|
|
|
server.listen(PORT, () => {
|
|
console.log('═══════════════════════════════════════════════════════');
|
|
console.log('🚀 Lokaler Reverse Proxy Server gestartet!');
|
|
console.log(`📡 Läuft auf: http://localhost:${PORT}`);
|
|
console.log('');
|
|
console.log('📌 Verwendung:');
|
|
console.log(` http://localhost:${PORT}/?lat=47.9385&lon=13.7629&apiKey=YOUR_KEY`);
|
|
console.log('');
|
|
console.log('⚠️ Hinweis: Nur für Entwicklung verwenden!');
|
|
console.log(' Für Produktion: Appwrite Function deployen');
|
|
console.log('═══════════════════════════════════════════════════════');
|
|
console.log('');
|
|
console.log('💡 Zum Beenden: Strg+C drücken');
|
|
console.log('');
|
|
});
|
|
|
|
// Graceful shutdown
|
|
process.on('SIGINT', () => {
|
|
console.log('\n\n👋 Server wird beendet...');
|
|
server.close(() => {
|
|
console.log('✅ Server erfolgreich gestoppt');
|
|
process.exit(0);
|
|
});
|
|
});
|