Enhance backend configuration and error handling: Update CORS settings to allow dynamic origins, improve RabbitMQ connection handling in chat services, and adjust API server host configuration. Refactor environment variables for better flexibility and add fallback mechanisms for WebSocket and chat services. Update frontend environment files for consistent API and WebSocket URLs.
This commit is contained in:
@@ -36,6 +36,11 @@ const app = express();
|
||||
// - LOG_ALL_REQ=1: Logge alle Requests
|
||||
const LOG_ALL_REQ = process.env.LOG_ALL_REQ === '1';
|
||||
const LOG_SLOW_REQ_MS = Number.parseInt(process.env.LOG_SLOW_REQ_MS || '500', 10);
|
||||
const corsOrigins = (process.env.CORS_ORIGINS || process.env.FRONTEND_URL || '')
|
||||
.split(',')
|
||||
.map((origin) => origin.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
app.use((req, res, next) => {
|
||||
const reqId = req.headers['x-request-id'] || (crypto.randomUUID ? crypto.randomUUID() : crypto.randomBytes(8).toString('hex'));
|
||||
req.reqId = reqId;
|
||||
@@ -51,15 +56,26 @@ app.use((req, res, next) => {
|
||||
});
|
||||
|
||||
const corsOptions = {
|
||||
origin: ['http://localhost:3000', 'http://localhost:5173', 'http://127.0.0.1:3000', 'http://127.0.0.1:5173'],
|
||||
origin(origin, callback) {
|
||||
if (!origin) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
if (corsOrigins.length === 0 || corsOrigins.includes(origin)) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
return callback(null, false);
|
||||
},
|
||||
methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'userId', 'authCode'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'userid', 'authcode', 'userId', 'authCode'],
|
||||
credentials: true,
|
||||
preflightContinue: false,
|
||||
optionsSuccessStatus: 204
|
||||
};
|
||||
|
||||
app.use(cors(corsOptions));
|
||||
app.options('*', cors(corsOptions));
|
||||
app.use(express.json()); // To handle JSON request bodies
|
||||
|
||||
app.use('/api/chat', chatRouter);
|
||||
|
||||
@@ -13,7 +13,8 @@ import { setupWebSocket } from './utils/socket.js';
|
||||
import { syncDatabase } from './utils/syncDatabase.js';
|
||||
|
||||
// HTTP-Server für API (Port 2020, intern, über Apache-Proxy)
|
||||
const API_PORT = Number.parseInt(process.env.PORT || '2020', 10);
|
||||
const API_PORT = Number.parseInt(process.env.API_PORT || process.env.PORT || '2020', 10);
|
||||
const API_HOST = process.env.API_HOST || '127.0.0.1';
|
||||
const httpServer = http.createServer(app);
|
||||
// Socket.io wird nur auf HTTPS-Server bereitgestellt, nicht auf HTTP-Server
|
||||
// setupWebSocket(httpServer); // Entfernt: Socket.io nur über HTTPS
|
||||
@@ -25,6 +26,7 @@ const USE_TLS = process.env.SOCKET_IO_TLS === '1';
|
||||
const TLS_KEY_PATH = process.env.SOCKET_IO_TLS_KEY_PATH;
|
||||
const TLS_CERT_PATH = process.env.SOCKET_IO_TLS_CERT_PATH;
|
||||
const TLS_CA_PATH = process.env.SOCKET_IO_TLS_CA_PATH;
|
||||
const SOCKET_IO_HOST = process.env.SOCKET_IO_HOST || '0.0.0.0';
|
||||
|
||||
if (USE_TLS && TLS_KEY_PATH && TLS_CERT_PATH) {
|
||||
try {
|
||||
@@ -45,14 +47,14 @@ if (USE_TLS && TLS_KEY_PATH && TLS_CERT_PATH) {
|
||||
|
||||
syncDatabase().then(() => {
|
||||
// API-Server auf Port 2020 (intern, nur localhost)
|
||||
httpServer.listen(API_PORT, '127.0.0.1', () => {
|
||||
console.log(`[API] HTTP-Server läuft auf localhost:${API_PORT} (intern, über Apache-Proxy)`);
|
||||
httpServer.listen(API_PORT, API_HOST, () => {
|
||||
console.log(`[API] HTTP-Server läuft auf ${API_HOST}:${API_PORT}`);
|
||||
});
|
||||
|
||||
// Socket.io-Server auf Port 4443 (extern, direkt erreichbar)
|
||||
if (httpsServer) {
|
||||
httpsServer.listen(SOCKET_IO_PORT, '0.0.0.0', () => {
|
||||
console.log(`[Socket.io] HTTPS-Server läuft auf Port ${SOCKET_IO_PORT} (direkt erreichbar)`);
|
||||
httpsServer.listen(SOCKET_IO_PORT, SOCKET_IO_HOST, () => {
|
||||
console.log(`[Socket.io] HTTPS-Server läuft auf ${SOCKET_IO_HOST}:${SOCKET_IO_PORT}`);
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import amqp from 'amqplib/callback_api.js';
|
||||
import User from '../models/community/user.js';
|
||||
import Room from '../models/chat/room.js';
|
||||
|
||||
const RABBITMQ_URL = 'amqp://localhost';
|
||||
const RABBITMQ_URL = process.env.AMQP_URL || 'amqp://localhost';
|
||||
const QUEUE = 'oneToOne_messages';
|
||||
|
||||
class ChatService {
|
||||
@@ -13,11 +13,37 @@ class ChatService {
|
||||
this.users = [];
|
||||
this.randomChats = [];
|
||||
this.oneToOneChats = [];
|
||||
this.channel = null;
|
||||
this.amqpAvailable = false;
|
||||
this.initRabbitMq();
|
||||
}
|
||||
|
||||
initRabbitMq() {
|
||||
amqp.connect(RABBITMQ_URL, (err, connection) => {
|
||||
if (err) throw err;
|
||||
connection.createChannel((err, channel) => {
|
||||
if (err) throw err;
|
||||
if (err) {
|
||||
console.warn(`[chatService] RabbitMQ nicht erreichbar (${RABBITMQ_URL}) - fallback ohne Queue wird verwendet.`);
|
||||
return;
|
||||
}
|
||||
|
||||
connection.on('error', (connectionError) => {
|
||||
console.warn('[chatService] RabbitMQ-Verbindung fehlerhaft:', connectionError.message);
|
||||
this.channel = null;
|
||||
this.amqpAvailable = false;
|
||||
});
|
||||
|
||||
connection.on('close', () => {
|
||||
console.warn('[chatService] RabbitMQ-Verbindung geschlossen.');
|
||||
this.channel = null;
|
||||
this.amqpAvailable = false;
|
||||
});
|
||||
|
||||
connection.createChannel((channelError, channel) => {
|
||||
if (channelError) {
|
||||
console.warn('[chatService] RabbitMQ-Channel konnte nicht erstellt werden:', channelError.message);
|
||||
return;
|
||||
}
|
||||
this.channel = channel;
|
||||
this.amqpAvailable = true;
|
||||
channel.assertQueue(QUEUE, { durable: false });
|
||||
});
|
||||
});
|
||||
@@ -118,7 +144,7 @@ class ChatService {
|
||||
history: [messageBundle],
|
||||
});
|
||||
}
|
||||
if (this.channel) {
|
||||
if (this.channel && this.amqpAvailable) {
|
||||
this.channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(messageBundle)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ import net from 'net';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const DEFAULT_CONFIG = { host: 'localhost', port: 1235 };
|
||||
const DEFAULT_CONFIG = {
|
||||
host: process.env.CHAT_TCP_HOST || 'localhost',
|
||||
port: Number.parseInt(process.env.CHAT_TCP_PORT || '1235', 10),
|
||||
};
|
||||
|
||||
function loadBridgeConfig() {
|
||||
try {
|
||||
|
||||
@@ -2,38 +2,59 @@
|
||||
import { Server } from 'socket.io';
|
||||
import amqp from 'amqplib/callback_api.js';
|
||||
|
||||
const RABBITMQ_URL = 'amqp://localhost';
|
||||
const RABBITMQ_URL = process.env.AMQP_URL || 'amqp://localhost';
|
||||
const QUEUE = 'chat_messages';
|
||||
|
||||
export function setupWebSocket(server) {
|
||||
const io = new Server(server);
|
||||
let channel = null;
|
||||
|
||||
amqp.connect(RABBITMQ_URL, (err, connection) => {
|
||||
if (err) throw err;
|
||||
if (err) {
|
||||
console.warn(`[webSocketService] RabbitMQ nicht erreichbar (${RABBITMQ_URL}) - WebSocket läuft ohne Queue-Bridge.`);
|
||||
return;
|
||||
}
|
||||
|
||||
connection.createChannel((err, channel) => {
|
||||
if (err) throw err;
|
||||
connection.on('error', (connectionError) => {
|
||||
console.warn('[webSocketService] RabbitMQ-Verbindung fehlerhaft:', connectionError.message);
|
||||
channel = null;
|
||||
});
|
||||
|
||||
connection.on('close', () => {
|
||||
console.warn('[webSocketService] RabbitMQ-Verbindung geschlossen.');
|
||||
channel = null;
|
||||
});
|
||||
|
||||
connection.createChannel((channelError, createdChannel) => {
|
||||
if (channelError) {
|
||||
console.warn('[webSocketService] RabbitMQ-Channel konnte nicht erstellt werden:', channelError.message);
|
||||
return;
|
||||
}
|
||||
|
||||
channel = createdChannel;
|
||||
channel.assertQueue(QUEUE, { durable: false });
|
||||
channel.consume(QUEUE, (msg) => {
|
||||
if (!msg) return;
|
||||
const message = JSON.parse(msg.content.toString());
|
||||
io.emit('newMessage', message);
|
||||
}, { noAck: true });
|
||||
});
|
||||
});
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
console.log('Client connected via WebSocket');
|
||||
io.on('connection', (socket) => {
|
||||
console.log('Client connected via WebSocket');
|
||||
|
||||
// Konsumiert Nachrichten aus RabbitMQ und sendet sie an den WebSocket-Client
|
||||
channel.consume(QUEUE, (msg) => {
|
||||
const message = JSON.parse(msg.content.toString());
|
||||
io.emit('newMessage', message); // Broadcast an alle Clients
|
||||
}, { noAck: true });
|
||||
socket.on('newMessage', (message) => {
|
||||
if (channel) {
|
||||
channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(message)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Empfangt eine Nachricht vom WebSocket-Client und sendet sie an die RabbitMQ-Warteschlange
|
||||
socket.on('newMessage', (message) => {
|
||||
channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(message)));
|
||||
});
|
||||
io.emit('newMessage', message);
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log('Client disconnected');
|
||||
});
|
||||
});
|
||||
socket.on('disconnect', () => {
|
||||
console.log('Client disconnected');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export function setupWebSocket(server) {
|
||||
|
||||
export function getIo() {
|
||||
if (!io) {
|
||||
throw new Error('Socket.io ist nicht initialisiert!');
|
||||
return null;
|
||||
}
|
||||
return io;
|
||||
}
|
||||
@@ -46,6 +46,10 @@ export function getUserSockets() {
|
||||
|
||||
export async function notifyUser(recipientHashedUserId, event, data) {
|
||||
const io = getIo();
|
||||
if (!io) {
|
||||
if (DEBUG_SOCKETS) console.warn('[socket.io] notifyUser übersprungen: Socket.io nicht initialisiert');
|
||||
return;
|
||||
}
|
||||
const userSockets = getUserSockets();
|
||||
try {
|
||||
const recipientUser = await baseService.getUserByHashedId(recipientHashedUserId);
|
||||
@@ -70,6 +74,10 @@ export async function notifyUser(recipientHashedUserId, event, data) {
|
||||
|
||||
export async function notifyAllUsers(event, data) {
|
||||
const io = getIo();
|
||||
if (!io) {
|
||||
if (DEBUG_SOCKETS) console.warn('[socket.io] notifyAllUsers übersprungen: Socket.io nicht initialisiert');
|
||||
return;
|
||||
}
|
||||
const userSockets = getUserSockets();
|
||||
|
||||
try {
|
||||
@@ -80,4 +88,4 @@ export async function notifyAllUsers(event, data) {
|
||||
} catch (err) {
|
||||
console.error('Fehler beim Senden der Benachrichtigung an alle Benutzer:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user