From a8f31ff23b01ba39b9d44ea3f521a0737e9f30a1 Mon Sep 17 00:00:00 2001 From: HlexNC Date: Mon, 1 Jul 2024 14:33:26 +0200 Subject: [PATCH 1/9] chore: Expose ports 5000, 5001 and 5002 in Docker Compose --- client/.env.examle | 1 + docker-compose.yml | 1 + server/Dockerfile | 2 +- server/package.json | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/.env.examle b/client/.env.examle index f7ce09c..e16b4b0 100644 --- a/client/.env.examle +++ b/client/.env.examle @@ -9,6 +9,7 @@ REACT_APP_SERVER_URL=https://localhost:5000 # WebSocket URL REACT_APP_WS_URL=wss://localhost:5001/ws +REACT_APP_WSS_URL=wss://localhost:5002/ws # SSL Certificate and Key (if needed for local development) SSL_CRT_FILE=/etc/ssl/certs/localhost.pem diff --git a/docker-compose.yml b/docker-compose.yml index 6bf3f5c..9c28e73 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,7 @@ services: image: hlexnc/devablos-project-v2-server platform: linux/amd64 ports: + - "5000:5000" - "5001:5001" - "5002:5002" volumes: diff --git a/server/Dockerfile b/server/Dockerfile index 8bee9f1..086ed8e 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -10,6 +10,6 @@ COPY . . COPY .env .env -EXPOSE 5001 5002 +EXPOSE 5000 5001 5002 CMD ["npm", "run", "start:pain"] diff --git a/server/package.json b/server/package.json index 35b4447..9cf2de7 100644 --- a/server/package.json +++ b/server/package.json @@ -7,7 +7,7 @@ "start:chat": "node ./src/sockets/wsServer_ChatGPT.js", "start:pain": "node ./src/sockets/wsServer_Assistant.js", "start:pain:secure": "node ./src/sockets/wssServer_Assistant.js", - "start:all": "concurrently \"npm run start:pain\" \"npm run start:pain:secure\"" + "start:all": "concurrently \"npm run start\" \"npm run start:pain\" \"npm run start:pain:secure\"" }, "dependencies": { "concurrently": "^8.2.2", From 529abdec6ce14a0447d121c8abdff508d13109aa Mon Sep 17 00:00:00 2001 From: HlexNC Date: Mon, 1 Jul 2024 20:22:51 +0200 Subject: [PATCH 2/9] chore: Update Dockerfile and server.js for WebSocket server implementation --- docker-compose.yml | 2 - server/Dockerfile | 4 +- server/src/server.js | 97 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9c28e73..93d1d01 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,8 +23,6 @@ services: platform: linux/amd64 ports: - "5000:5000" - - "5001:5001" - - "5002:5002" volumes: - D:/Devablos-Project-V2/.certs:/etc/ssl/certs - D:/Devablos-Project-V2/.private:/etc/ssl/private diff --git a/server/Dockerfile b/server/Dockerfile index 086ed8e..9225484 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -10,6 +10,6 @@ COPY . . COPY .env .env -EXPOSE 5000 5001 5002 +EXPOSE 5000 -CMD ["npm", "run", "start:pain"] +CMD ["npm", "start"] diff --git a/server/src/server.js b/server/src/server.js index 62a1178..418c8da 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -1,8 +1,15 @@ const https = require('https'); const http = require('http'); const fs = require('fs'); +const WebSocket = require('ws'); +const express = require('express'); +const dotenv = require('dotenv'); +const clients = require('./utils/connection'); +const assistantServices = require('./services/assistantService'); const app = require('./app'); +dotenv.config(); + // Read SSL key and certificate const credentials = { key: fs.readFileSync(process.env.SSL_KEY_PATH, 'utf8'), @@ -55,13 +62,85 @@ httpsServer.listen(port); httpsServer.on('error', onError); httpsServer.on('listening', onListening); -// HTTP server for redirection -const httpPort = 80; -const httpServer = http.createServer((req, res) => { - res.writeHead(301, { "Location": `https://${req.headers['host']}${req.url}` }); - res.end(); -}); +// WebSocket server for ws:// and wss:// +const wss = new WebSocket.Server({ server: httpsServer }); + +// Define the handleConnection function +const handleConnection = (ws, req) => { + console.log("New client connected!"); + let sessionId, user_message; + + ws.on('message', async (message) => { + try { + const parsedMsg = JSON.parse(message); + const { action, data } = parsedMsg; + + switch (action) { + case 'validateSession': + ({ sessionId } = data); + if (clients.has(sessionId)) { + ws.send(JSON.stringify({ action: 'sessionValidated', valid: true, sessionId })); + } else { + sessionId = await assistantServices.create_user(); + ws.send(JSON.stringify({ action: 'sessionValidated', valid: false, sessionId })); + } + break; + + case 'createSession': + sessionId = await assistantServices.create_user(); + ws.send(JSON.stringify({ action: 'sessionValidated', valid: false, sessionId })); + break; + + case 'sendMessage': + ({ sessionId, user_message } = data); + if (!clients.has(sessionId)) { + console.error('Session not found:', sessionId); + ws.send(JSON.stringify({ error: 'Session not found' })); + return; + } + let assistant = clients.get(sessionId).assistant; + const assistant_message = await assistantServices.sendMessage(sessionId, user_message); + ws.send(JSON.stringify({ action: 'assistantMessage', assistant_message })); + break; + + case 'deleteSession': + ({ sessionId } = data); + console.log(sessionId); + if (clients.has(sessionId)) { + assistantServices.deleteSession(sessionId); + } + break; + + default: + if (!data || !data.sessionId) { + ws.send(JSON.stringify({ error: 'No sessionId provided' })); + return; + } + break; + } + } catch (error) { + ws.send(JSON.stringify({ error: error.message })); + } + }); + + ws.on('close', () => { + if (sessionId && clients.has(sessionId)) { + console.log(`Client disconnected. Session ${sessionId} removed.`); + } else { + console.log("Client disconnected."); + } + }); + + ws.on('error', (error) => { + console.error(`WebSocket error:`, error); + }); + + setTimeout(() => { + if (ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ message: 'Session is being kept alive.' })); + } + }, 14 * 60 * 1000); // 14 minutes to send a keep-alive message +}; -httpServer.listen(httpPort, () => { - console.log(`HTTP Server listening on port ${httpPort} and redirecting to HTTPS`); -}); +// Use the handleConnection function for WebSocket connections +wss.on('connection', handleConnection); From 3da94d4abcd15d47a7f97d0e685d2d875d3a8ec1 Mon Sep 17 00:00:00 2001 From: HlexNC Date: Mon, 1 Jul 2024 22:22:19 +0200 Subject: [PATCH 3/9] chore: Update Dockerfile and server.js for WebSocket server implementation --- client/.env.examle | 4 --- client/Dockerfile | 1 - client/src/App.js | 70 +++++++++++++++------------------------------ server/.env.example | 6 ---- 4 files changed, 23 insertions(+), 58 deletions(-) diff --git a/client/.env.examle b/client/.env.examle index e16b4b0..e20a856 100644 --- a/client/.env.examle +++ b/client/.env.examle @@ -7,10 +7,6 @@ PORT=3000 # Server URL REACT_APP_SERVER_URL=https://localhost:5000 -# WebSocket URL -REACT_APP_WS_URL=wss://localhost:5001/ws -REACT_APP_WSS_URL=wss://localhost:5002/ws - # SSL Certificate and Key (if needed for local development) SSL_CRT_FILE=/etc/ssl/certs/localhost.pem SSL_KEY_FILE=/etc/ssl/private/localhost-key.pem diff --git a/client/Dockerfile b/client/Dockerfile index 51f8475..368e66d 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -16,5 +16,4 @@ COPY .env .env EXPOSE 3000 - CMD ["serve", "-s", "build", "-l", "3000", "--ssl-cert", "/etc/ssl/certs/localhost.pem", "--ssl-key", "/etc/ssl/private/localhost-key.pem"] diff --git a/client/src/App.js b/client/src/App.js index 4f8228d..5135947 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -4,23 +4,21 @@ import Chat from './components/Chat'; import Navbar from './components/Navbar'; import './App.css'; -const WSS_URL = process.env.REACT_APP_WSS_URL || `wss://${window.location.hostname}:5002`; -const WS_URL = process.env.REACT_APP_WS_URL || `ws://${window.location.hostname}:5001`; +const HTTPS_URL = process.env.REACT_APP_SERVER_URL || `https://${window.location.hostname}:5000`; function App() { - const [socketUrl, setSocketUrl] = useState(WSS_URL); + const [socketUrl, setSocketUrl] = useState(HTTPS_URL); const [sessionId, setSessionId] = useState(localStorage.getItem('sessionId') || null); const [messages, setMessages] = useState(() => { const savedMessages = localStorage.getItem('chatHistory'); return savedMessages ? JSON.parse(savedMessages) : [{ role: 'system', content: 'You are Devabot ✨, a funny helpful assistant.' }]; }); const [isConnected, setIsConnected] = useState(false); - const [fallbackAttempted, setFallbackAttempted] = useState(false); const validateOrCreateSession = useCallback(() => { if (sessionId) { console.log('Validating existing session:', sessionId); - sendMessage(JSON.stringify({ action: 'validateSession', data: { sessionId: sessionId } })); + sendMessage(JSON.stringify({ action: 'validateSession', data: { sessionId } })); } else { console.log('Creating new session'); sendMessage(JSON.stringify({ action: 'createSession' })); @@ -30,28 +28,20 @@ function App() { const handleOpen = useCallback(() => { console.log('WebSocket connected'); setIsConnected(true); - }); + }, []); const handleClose = useCallback(() => { console.log('WebSocket disconnected'); setIsConnected(false); - if (!fallbackAttempted) { - console.log('Attempting fallback to WS'); - setSocketUrl(WS_URL); - setFallbackAttempted(true); - } - }, [fallbackAttempted]); + setSocketUrl(HTTPS_URL); + }, []); const handleError = useCallback( (error) => { console.error('WebSocket error:', error); - if (!fallbackAttempted) { - console.log('Error occurred, attempting fallback to WS'); - setSocketUrl(WS_URL); - setFallbackAttempted(true); - } + setSocketUrl(HTTPS_URL); }, - [fallbackAttempted] + [] ); const handleMessage = useCallback( @@ -59,34 +49,24 @@ function App() { try { const parsedData = JSON.parse(message.data); console.log('Received WebSocket message:', parsedData); - + switch (parsedData.action) { case 'sessionValidated': - if (parsedData.valid) { - console.log('Session validated:', parsedData.sessionId); - } else { - console.log('Session invalid, creating new session'); - } - // Always update the sessionId, whether it's validated or new setSessionId(parsedData.sessionId); localStorage.setItem('sessionId', parsedData.sessionId); - break; + break; case 'assistantMessage': - const returned_message = parsedData.assistant_message; - const newMessage = { role: 'assistant', content: returned_message }; - setMessages((prevMessages) => { - const updatedMessages = [...prevMessages, newMessage]; - return updatedMessages; - }); + const returnedMessage = parsedData.assistant_message; + const newMessage = { role: 'assistant', content: returnedMessage }; + setMessages((prevMessages) => [...prevMessages, newMessage]); break; - + case 'chatHistory': - console.log('Received chat history'); setMessages(parsedData.messages); localStorage.setItem('chatHistory', JSON.stringify(parsedData.messages)); break; - + default: console.log('Unknown WebSocket message received:', parsedData); break; @@ -95,15 +75,15 @@ function App() { console.error('Error parsing WebSocket message:', error); } }, - [sessionId, setSessionId, setMessages] + [sessionId] ); - const { sendMessage, lastMessage, readyState, reconnect } = useWebSocket(socketUrl, { + const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl, { onOpen: handleOpen, onClose: handleClose, onError: handleError, onMessage: handleMessage, - shouldReconnect: (closeEvent) => !fallbackAttempted, + shouldReconnect: (closeEvent) => true, reconnectAttempts: 20, reconnectInterval: 3000, }); @@ -111,12 +91,11 @@ function App() { const clearHistory = useCallback(() => { localStorage.removeItem('chatHistory'); setMessages([{ role: 'system', content: 'You are Devabot ✨, a funny helpful assistant.' }]); - + if (isConnected) { - sendMessage(JSON.stringify({ action: 'deleteSession', data: { sessionId: sessionId } })); + sendMessage(JSON.stringify({ action: 'deleteSession', data: { sessionId } })); localStorage.removeItem('sessionId'); setSessionId(null); - // Instead of immediately creating a new session, we'll wait for the next connection } }, [isConnected, sendMessage, sessionId]); @@ -125,13 +104,13 @@ function App() { const updatedMessages = [...messages, newMessage]; setMessages(updatedMessages); localStorage.setItem('chatHistory', JSON.stringify(updatedMessages)); - + if (isConnected) { sendMessage( JSON.stringify({ action: 'sendMessage', data: { - sessionId: sessionId, + sessionId, user_message: message, }, }) @@ -146,7 +125,6 @@ function App() { case ReadyState.CONNECTING: return '🔄 Connecting'; case ReadyState.OPEN: - console.log('WebSocket Ready!'); return '🟢 Connected'; case ReadyState.CLOSING: return '🟠 Closing'; @@ -159,7 +137,6 @@ function App() { useEffect(() => { if (readyState === ReadyState.OPEN) { - setFallbackAttempted(false); if (sessionId) { validateOrCreateSession(); } else { @@ -170,12 +147,11 @@ function App() { useEffect(() => { localStorage.setItem('chatHistory', JSON.stringify(messages)); - console.log('Saved messages to localStorage:', messages); }, [messages]); return (
- + setSocketUrl(HTTPS_URL)} onClearHistory={clearHistory} />
); diff --git a/server/.env.example b/server/.env.example index fc01c2a..88bffbc 100644 --- a/server/.env.example +++ b/server/.env.example @@ -4,12 +4,6 @@ # Port number PORT=5000 -# WebSocket port -WS_PORT=5001 - -# WebSocket Secure port -WSS_PORT=5001 - # CORS origin CORS_ORIGIN=https://localhost:3000 From ecd531631d758413badb0fab2c3936d63182cb7f Mon Sep 17 00:00:00 2001 From: HlexNC Date: Mon, 1 Jul 2024 23:34:48 +0200 Subject: [PATCH 4/9] chore: Update server URLs to use HTTPS instead of HTTP --- client/src/App.js | 112 ++++++++++-------- server/src/controllers/assistantController.js | 2 + server/src/server.js | 19 ++- server/swagger.js | 2 +- 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index 5135947..d9a02fa 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -4,10 +4,11 @@ import Chat from './components/Chat'; import Navbar from './components/Navbar'; import './App.css'; -const HTTPS_URL = process.env.REACT_APP_SERVER_URL || `https://${window.location.hostname}:5000`; +const SERVER_URL = process.env.REACT_APP_SERVER_URL || 'https://localhost:5000'; -function App() { - const [socketUrl, setSocketUrl] = useState(HTTPS_URL); +const App = () => { + const [useWebSocketProtocol, setUseWebSocketProtocol] = useState(true); + const [socketUrl, setSocketUrl] = useState(`${SERVER_URL.replace(/^http/, 'ws')}`); const [sessionId, setSessionId] = useState(localStorage.getItem('sessionId') || null); const [messages, setMessages] = useState(() => { const savedMessages = localStorage.getItem('chatHistory'); @@ -15,34 +16,29 @@ function App() { }); const [isConnected, setIsConnected] = useState(false); + const { + sendMessage: sendWebSocketMessage, + lastMessage, + readyState, + } = useWebSocket(socketUrl, { + onOpen: () => setIsConnected(true), + onClose: () => setIsConnected(false), + onError: (error) => console.error('WebSocket error:', error), + onMessage: (message) => handleMessage(message), + shouldReconnect: () => true, + reconnectAttempts: 20, + reconnectInterval: 3000, + }); + const validateOrCreateSession = useCallback(() => { if (sessionId) { console.log('Validating existing session:', sessionId); - sendMessage(JSON.stringify({ action: 'validateSession', data: { sessionId } })); + sendWebSocketMessage(JSON.stringify({ action: 'validateSession', data: { sessionId } })); } else { console.log('Creating new session'); - sendMessage(JSON.stringify({ action: 'createSession' })); + sendWebSocketMessage(JSON.stringify({ action: 'createSession' })); } - }, [sessionId]); - - const handleOpen = useCallback(() => { - console.log('WebSocket connected'); - setIsConnected(true); - }, []); - - const handleClose = useCallback(() => { - console.log('WebSocket disconnected'); - setIsConnected(false); - setSocketUrl(HTTPS_URL); - }, []); - - const handleError = useCallback( - (error) => { - console.error('WebSocket error:', error); - setSocketUrl(HTTPS_URL); - }, - [] - ); + }, [sessionId, sendWebSocketMessage]); const handleMessage = useCallback( (message) => { @@ -78,35 +74,24 @@ function App() { [sessionId] ); - const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl, { - onOpen: handleOpen, - onClose: handleClose, - onError: handleError, - onMessage: handleMessage, - shouldReconnect: (closeEvent) => true, - reconnectAttempts: 20, - reconnectInterval: 3000, - }); - const clearHistory = useCallback(() => { localStorage.removeItem('chatHistory'); setMessages([{ role: 'system', content: 'You are Devabot ✨, a funny helpful assistant.' }]); if (isConnected) { - sendMessage(JSON.stringify({ action: 'deleteSession', data: { sessionId } })); + sendWebSocketMessage(JSON.stringify({ action: 'deleteSession', data: { sessionId } })); localStorage.removeItem('sessionId'); setSessionId(null); } - }, [isConnected, sendMessage, sessionId]); + }, [isConnected, sendWebSocketMessage, sessionId]); const sendMessageHandler = async (message) => { const newMessage = { role: 'user', content: message }; const updatedMessages = [...messages, newMessage]; setMessages(updatedMessages); - localStorage.setItem('chatHistory', JSON.stringify(updatedMessages)); - if (isConnected) { - sendMessage( + if (useWebSocketProtocol && isConnected) { + sendWebSocketMessage( JSON.stringify({ action: 'sendMessage', data: { @@ -116,7 +101,33 @@ function App() { }) ); } else { - console.error('WebSocket is not connected. Unable to send message.'); + try { + const response = await fetch(`${SERVER_URL}/api/openai/assistant/sendMessage`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify({ + sessionID: sessionId, + prompt: message, + }), + }); + + if (!response.ok) { + const errorData = await response.json(); + console.error('Error response from server:', errorData); + throw new Error(`Error: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + console.log('Response data:', data); + const returnedMessage = data.assistant_message || data; + const newAssistantMessage = { role: 'assistant', content: returnedMessage }; + setMessages((prevMessages) => [...prevMessages, newAssistantMessage]); + } catch (error) { + console.error('Error sending message:', error); + } } }; @@ -137,24 +148,27 @@ function App() { useEffect(() => { if (readyState === ReadyState.OPEN) { - if (sessionId) { - validateOrCreateSession(); - } else { - sendMessage(JSON.stringify({ action: 'createSession' })); - } + validateOrCreateSession(); } - }, [readyState, sessionId, validateOrCreateSession, sendMessage]); + }, [readyState, validateOrCreateSession]); useEffect(() => { localStorage.setItem('chatHistory', JSON.stringify(messages)); }, [messages]); + const toggleProtocol = () => { + setUseWebSocketProtocol((prev) => !prev); + }; + return (
- setSocketUrl(HTTPS_URL)} onClearHistory={clearHistory} /> + setSocketUrl(`${SERVER_URL.replace(/^http/, 'ws')}`)} onClearHistory={clearHistory} /> +
); -} +}; export default App; diff --git a/server/src/controllers/assistantController.js b/server/src/controllers/assistantController.js index 6ccab0a..2919d8d 100644 --- a/server/src/controllers/assistantController.js +++ b/server/src/controllers/assistantController.js @@ -59,6 +59,7 @@ async function sendMessageHandler(req, res, next) { try { const { sessionID, prompt } = req.body; + console.log(sessionID, prompt); if (!prompt) { return res.status(400).json({ error: "Prompt is required" }); @@ -69,6 +70,7 @@ async function sendMessageHandler(req, res, next) { } const response = await sendMessage(sessionID, prompt); + console.log(response); res.json(response); } catch (error) { next(error); diff --git a/server/src/server.js b/server/src/server.js index 418c8da..ef5e349 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -1,5 +1,4 @@ const https = require('https'); -const http = require('http'); const fs = require('fs'); const WebSocket = require('ws'); const express = require('express'); @@ -17,7 +16,7 @@ const credentials = { }; // Create HTTPS server -const httpsServer = https.createServer(credentials, app); +const server = https.createServer(credentials, app); // Normalize a port into a number, string, or false const normalizePort = val => { @@ -30,7 +29,7 @@ const normalizePort = val => { const port = normalizePort(process.env.PORT || '5000'); app.set('port', port); -// Error handler for HTTP server +// Error handler for server const onError = error => { if (error.syscall !== 'listen') { throw error; @@ -50,20 +49,20 @@ const onError = error => { } }; -// Event listener for HTTP server "listening" event +// Event listener for server "listening" event const onListening = () => { - const addr = httpsServer.address(); + const addr = server.address(); const bind = typeof addr === 'string' ? 'Pipe ' + addr : 'Port ' + addr.port; console.log('Listening on ' + bind); }; // Listen on provided port, on all network interfaces -httpsServer.listen(port); -httpsServer.on('error', onError); -httpsServer.on('listening', onListening); +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); -// WebSocket server for ws:// and wss:// -const wss = new WebSocket.Server({ server: httpsServer }); +// WebSocket server +const wss = new WebSocket.Server({ server }); // Define the handleConnection function const handleConnection = (ws, req) => { diff --git a/server/swagger.js b/server/swagger.js index cf9760f..eaef0b2 100644 --- a/server/swagger.js +++ b/server/swagger.js @@ -11,7 +11,7 @@ const doc = { }, servers: [ { - url: `http://localhost:${process.env.PORT || '5000'}/`, + url: `https://localhost:${process.env.PORT || '5000'}/`, description: 'localhost', }, { From dd38eaf883fce9847e05369ea4202520b4696262 Mon Sep 17 00:00:00 2001 From: HlexNC Date: Tue, 2 Jul 2024 13:50:16 +0200 Subject: [PATCH 5/9] Update support for both HTTP and HTTPS servers --- client/.env.examle | 4 ++-- client/Dockerfile | 3 ++- docker-compose.yml | 8 ++++---- server/.env.example | 3 +++ server/src/server.js | 23 +++++++++++++++-------- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/client/.env.examle b/client/.env.examle index e20a856..53698d0 100644 --- a/client/.env.examle +++ b/client/.env.examle @@ -8,5 +8,5 @@ PORT=3000 REACT_APP_SERVER_URL=https://localhost:5000 # SSL Certificate and Key (if needed for local development) -SSL_CRT_FILE=/etc/ssl/certs/localhost.pem -SSL_KEY_FILE=/etc/ssl/private/localhost-key.pem +# SSL_CRT_FILE=/etc/ssl/certs/localhost.pem +# SSL_KEY_FILE=/etc/ssl/private/localhost-key.pem diff --git a/client/Dockerfile b/client/Dockerfile index 368e66d..eefd65a 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -16,4 +16,5 @@ COPY .env .env EXPOSE 3000 -CMD ["serve", "-s", "build", "-l", "3000", "--ssl-cert", "/etc/ssl/certs/localhost.pem", "--ssl-key", "/etc/ssl/private/localhost-key.pem"] +# CMD ["serve", "-s", "build", "-l", "3000", "--ssl-cert", "/etc/ssl/certs/localhost.pem", "--ssl-key", "/etc/ssl/private/localhost-key.pem"] +CMD ["serve", "-s", "build", "-l", "3000"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 93d1d01..eb88fdd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,10 +7,10 @@ services: platform: linux/amd64 ports: - "3000:3000" - environment: - - HTTPS=true - - SSL_CRT_FILE=/etc/ssl/certs/localhost.pem - - SSL_KEY_FILE=/etc/ssl/private/localhost-key.pem + # environment: + # - HTTPS=true + # - SSL_CRT_FILE=/etc/ssl/certs/localhost.pem + # - SSL_KEY_FILE=/etc/ssl/private/localhost-key.pem volumes: - D:/Devablos-Project-V2/.certs:/etc/ssl/certs - D:/Devablos-Project-V2/.private:/etc/ssl/private diff --git a/server/.env.example b/server/.env.example index 88bffbc..8106b8b 100644 --- a/server/.env.example +++ b/server/.env.example @@ -17,3 +17,6 @@ OPENWEATHER_API_KEY=your_openweather_api_key # SSL key and cert paths SSL_KEY_PATH=/etc/ssl/private/localhost-key.pem SSL_CERT_PATH=/etc/ssl/certs/localhost.pem + +# Use SSL +USE_SSL=true \ No newline at end of file diff --git a/server/src/server.js b/server/src/server.js index ef5e349..5520e97 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -1,4 +1,5 @@ const https = require('https'); +const http = require('http'); const fs = require('fs'); const WebSocket = require('ws'); const express = require('express'); @@ -9,14 +10,7 @@ const app = require('./app'); dotenv.config(); -// Read SSL key and certificate -const credentials = { - key: fs.readFileSync(process.env.SSL_KEY_PATH, 'utf8'), - cert: fs.readFileSync(process.env.SSL_CERT_PATH, 'utf8') -}; - -// Create HTTPS server -const server = https.createServer(credentials, app); +const useHttps = process.env.USE_SSL === 'true'; // Normalize a port into a number, string, or false const normalizePort = val => { @@ -27,6 +21,19 @@ const normalizePort = val => { }; const port = normalizePort(process.env.PORT || '5000'); + +let server; + +if (useHttps) { + const credentials = { + key: fs.readFileSync(process.env.SSL_KEY_PATH, 'utf8'), + cert: fs.readFileSync(process.env.SSL_CERT_PATH, 'utf8'), + }; + server = https.createServer(credentials, app); +} else { + server = http.createServer(app); +} + app.set('port', port); // Error handler for server From 517a100288b264d4ff566d5b80888e6a41503a31 Mon Sep 17 00:00:00 2001 From: Denisa <112165840+Reptilian6163@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:32:43 +0200 Subject: [PATCH 6/9] Update App.js --- client/src/App.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index d9a02fa..ef2916c 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -132,17 +132,18 @@ const App = () => { }; const getStatus = () => { + const protocolIndicator = currentProtocol === 'WSS' ? '🌐' : '🔒'; switch (readyState) { case ReadyState.CONNECTING: - return '🔄 Connecting'; + return `${protocolIndicator} 🔄 Connecting`; case ReadyState.OPEN: - return '🟢 Connected'; + return `${protocolIndicator} 🟢 Connected`; case ReadyState.CLOSING: - return '🟠 Closing'; + return `${protocolIndicator} 🟠 Closing`; case ReadyState.CLOSED: - return '🔴 Closed'; + return currentProtocol === 'HTTPS' ? '🔒 🟢 HTTPS' : `${protocolIndicator} 🔴 Closed`; default: - return '⚪ Unknown'; + return `${protocolIndicator} ⚪ Unknown`; } }; @@ -160,15 +161,23 @@ const App = () => { setUseWebSocketProtocol((prev) => !prev); }; - return ( -
- setSocketUrl(`${SERVER_URL.replace(/^http/, 'ws')}`)} onClearHistory={clearHistory} /> - - -
- ); + // In App.js +return ( +
+ setSocketUrl(`${SERVER_URL.replace(/^http/, 'ws')}`)} + onClearHistory={clearHistory} + useWebSocketProtocol={useWebSocketProtocol} + onToggleProtocol={toggleProtocol} + /> + {/* Remove this button */} + {/* */} + +
+); }; export default App; From 30cc01d21830b7714f3e9c89f5478432ccc7d72a Mon Sep 17 00:00:00 2001 From: Denisa <112165840+Reptilian6163@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:33:02 +0200 Subject: [PATCH 7/9] Update Navbar.css --- client/src/components/Navbar.css | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/client/src/components/Navbar.css b/client/src/components/Navbar.css index 75e937b..0158889 100644 --- a/client/src/components/Navbar.css +++ b/client/src/components/Navbar.css @@ -14,11 +14,28 @@ height: 60px; } +.status-container { + display: flex; + align-items: center; + margin-left: auto; +} + .status { cursor: pointer; font-size: 2vh; - margin-right: 2vh; - margin-left: auto; + margin-right: 1vh; +} + +.toggle-protocol { + cursor: pointer; + background-color: #007bff; + color: white; + border: none; + font-size: 2vh; + padding: 5px 10px; + border-radius: 5px; + margin-right: 1vh; + min-width: 100px; /* Ensure the button doesn't change size when text changes */ } .clear-chat { @@ -30,5 +47,4 @@ padding: 5px 10px; border-radius: 5px; margin-right: 5vh; - margin-left: 20px; } From 96f2f605fa7cd9e60b8d53429748f6df58f9c38e Mon Sep 17 00:00:00 2001 From: Denisa <112165840+Reptilian6163@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:33:16 +0200 Subject: [PATCH 8/9] Update Navbar.js --- client/src/components/Navbar.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/src/components/Navbar.js b/client/src/components/Navbar.js index cfad960..93f37a3 100644 --- a/client/src/components/Navbar.js +++ b/client/src/components/Navbar.js @@ -3,11 +3,16 @@ import './Navbar.css'; import WebSocketStatus from './WebSocketStatus'; import logo from '../logo.svg'; -const Navbar = ({ status, onReconnect, onClearHistory }) => { +const Navbar = ({ status, onReconnect, onClearHistory, useWebSocketProtocol, onToggleProtocol }) => { return (
Devablos Project Logo - +
+ + +
); From 497d82624bc3e5ce4aa0edd915cb5b2f951055b7 Mon Sep 17 00:00:00 2001 From: HlexNC Date: Wed, 3 Jul 2024 12:48:26 +0200 Subject: [PATCH 9/9] fixed the toggle protocol button in App.js --- client/src/App.js | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index ef2916c..c5e9a7a 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -70,8 +70,7 @@ const App = () => { } catch (error) { console.error('Error parsing WebSocket message:', error); } - }, - [sessionId] + }, [sessionId] ); const clearHistory = useCallback(() => { @@ -132,6 +131,7 @@ const App = () => { }; const getStatus = () => { + const currentProtocol = useWebSocketProtocol ? 'WSS' : 'HTTPS'; const protocolIndicator = currentProtocol === 'WSS' ? '🌐' : '🔒'; switch (readyState) { case ReadyState.CONNECTING: @@ -161,23 +161,18 @@ const App = () => { setUseWebSocketProtocol((prev) => !prev); }; - // In App.js -return ( -
- setSocketUrl(`${SERVER_URL.replace(/^http/, 'ws')}`)} - onClearHistory={clearHistory} - useWebSocketProtocol={useWebSocketProtocol} - onToggleProtocol={toggleProtocol} - /> - {/* Remove this button */} - {/* */} - -
-); + return ( +
+ setSocketUrl(`${SERVER_URL.replace(/^http/, 'ws')}`)} + onClearHistory={clearHistory} + useWebSocketProtocol={useWebSocketProtocol} + onToggleProtocol={toggleProtocol} + /> + +
+ ); }; export default App;