From 1cde2eb646303a71a11b42027e54a1a72eabb52f Mon Sep 17 00:00:00 2001 From: guowei42 <65711401+guowei42@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:01:19 +0800 Subject: [PATCH 1/2] fix cors for socket --- api-gateway/api.conf | 8 +- client/.env.template | 2 +- client/src/socket.js | 39 ++++-- server/chat-service/server.js | 1 + server/collaboration-service/server.js | 1 + server/matching-service/server.js | 172 ++++++++++++++----------- 6 files changed, 133 insertions(+), 90 deletions(-) diff --git a/api-gateway/api.conf b/api-gateway/api.conf index ffd1fbbfe3..0021834ec6 100644 --- a/api-gateway/api.conf +++ b/api-gateway/api.conf @@ -27,7 +27,7 @@ server { } location /questions { - proxy_pass http://questions_service; + proxy_pass http://questions_service/questions; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -46,7 +46,7 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://matching_service/; + proxy_pass http://matching_service/matching/; # socket support proxy_http_version 1.1; @@ -58,7 +58,7 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://chat_service/; + proxy_pass http://chat_service/chat/; # socket support proxy_http_version 1.1; @@ -70,7 +70,7 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://collab_service/; + proxy_pass http://collab_service/collaboration/; # socket support proxy_http_version 1.1; diff --git a/client/.env.template b/client/.env.template index a9e531ac5e..b7fe4e95f9 100644 --- a/client/.env.template +++ b/client/.env.template @@ -3,4 +3,4 @@ # API endpoints # without port -REACT_APP_API_BASE_URL=http://localhost +REACT_APP_API_BASE_URL=http://localhost \ No newline at end of file diff --git a/client/src/socket.js b/client/src/socket.js index c933b4dc5a..bdc7433916 100644 --- a/client/src/socket.js +++ b/client/src/socket.js @@ -1,14 +1,33 @@ import { SVC_ENDPOINTS } from "./consts/api"; -import { io } from 'socket.io-client'; +import { io } from "socket.io-client"; -export const matchingSocket = io(SVC_ENDPOINTS.matching, { - autoConnect: false -}) +const isProduction = + process.env.REACT_APP_API_BASE_URL && + process.env.REACT_APP_API_BASE_URL !== "http://localhost"; -export const collaborationSocket = io(SVC_ENDPOINTS.collaboration, { - autoConnect: false -}) +export const matchingSocket = isProduction + ? io(process.env.REACT_APP_API_BASE_URL, { + path: "/matching", + autoConnect: false, + }) + : io(SVC_ENDPOINTS.matching, { + autoConnect: false, + }); -export const chatSocket = io(SVC_ENDPOINTS.chat, { - autoConnect: false -}) \ No newline at end of file +export const collaborationSocket = isProduction + ? io(process.env.REACT_APP_API_BASE_URL, { + path: "/collaboration", + autoConnect: false, + }) + : io(SVC_ENDPOINTS.collaboration, { + autoConnect: false, + }); + +export const chatSocket = isProduction + ? io(process.env.REACT_APP_API_BASE_URL, { + path: "/chat", + autoConnect: false, + }) + : io(SVC_ENDPOINTS.chat, { + autoConnect: false, + }); diff --git a/server/chat-service/server.js b/server/chat-service/server.js index dc5c0d38e3..14c20d1903 100644 --- a/server/chat-service/server.js +++ b/server/chat-service/server.js @@ -5,6 +5,7 @@ const port = process.env.PORT || 3006; // Ensure this matches SVC_PORTS for chat const server = http.createServer(); const io = new Server(server, { + path: "/chat", cors: { origin: ["http://localhost:3000", "https://peerprep-nine.vercel.app"], methods: "GET, POST, DELETE, PUT, PATCH", diff --git a/server/collaboration-service/server.js b/server/collaboration-service/server.js index 0637cef206..83b7f2aabd 100644 --- a/server/collaboration-service/server.js +++ b/server/collaboration-service/server.js @@ -5,6 +5,7 @@ const port = process.env.PORT || 3004; const server = http.createServer(); const io = new Server(server, { + path: "/collaboration", cors: { origin: ["http://localhost:3000", "https://peerprep-nine.vercel.app"], methods: "GET, POST, DELETE, PUT, PATCH", diff --git a/server/matching-service/server.js b/server/matching-service/server.js index 02fbfdd0be..1d38960c38 100644 --- a/server/matching-service/server.js +++ b/server/matching-service/server.js @@ -9,108 +9,130 @@ const redis_url = process.env.REDIS_URL; const server = http.createServer(); const io = new Server(server, { + path: "/matching", cors: { - origin: ["http://localhost:3000", "https://peerprep-nine.vercel.app"], + origin: true, methods: "GET, POST, DELETE, PUT, PATCH", - allowedHeaders: "Origin, X-Requested-With, Content-Type, Accept, Authorization, Cookie", - credentials: true -} + allowedHeaders: + "Origin, X-Requested-With, Content-Type, Accept, Authorization, Cookie", + credentials: true, + }, }); + const redisClient = redis.createClient({ - url: redis_url - }); + url: redis_url, +}); async function connectRedis() { - try { - await redisClient.connect(); - console.log("Connected to Redis"); - } catch (err) { - console.error("Redis connection error:", err); - } + try { + await redisClient.connect(); + console.log("Connected to Redis"); + } catch (err) { + console.error("Redis connection error:", err); + } } connectRedis(); io.on("connection", (socket) => { - console.log(`Client connected: ${socket.id}`); - - socket.on("requestMatch", async ({ userId, topic, difficulty }) => { - socket.userId = userId; - socket.topic = topic; - socket.difficulty = difficulty; - - await redisClient.rPush(`${topic}`, JSON.stringify({ userId, difficulty })); - - socket.timeoutId = setTimeout(async () => { - removeUser(userId, topic, difficulty) - socket.emit("matchUpdate", { status: "timeout", message: "No match found within 30 seconds." }); - await redisClient.lRem(`${topic}`, 1, JSON.stringify({ userId, difficulty })); - }, 30000); - - const match = await findMatch(userId, topic, difficulty); - if (match) { - clearTimeout(socket.timeoutId); - const room_id = randomUUID(); - var temp_difficulty = difficulty; - if (temp_difficulty === null) { - temp_difficulty = "Easy"; - } - socket.emit("matchUpdate", { status: "match_found", userId: userId, partnerId: match.userId, roomId: room_id, difficulty: temp_difficulty}); - const matchedSocket = findSocketByUserId(match.userId); - if (matchedSocket) { - clearTimeout(matchedSocket.timeoutId); - matchedSocket.emit("matchUpdate", { status: "match_found", userId: match.userId, partnerId: userId, roomId:room_id, difficulty: temp_difficulty }); - } - await removeUser(userId, topic, difficulty); - } - }); - - socket.on("disconnect", async () => { - const { userId, topic, difficulty } = socket; - await removeUser(userId, topic, difficulty); - console.log(`Client disconnected: ${socket.id}`); - }); + console.log(`Client connected: ${socket.id}`); + + socket.on("requestMatch", async ({ userId, topic, difficulty }) => { + socket.userId = userId; + socket.topic = topic; + socket.difficulty = difficulty; + + await redisClient.rPush(`${topic}`, JSON.stringify({ userId, difficulty })); + + socket.timeoutId = setTimeout(async () => { + removeUser(userId, topic, difficulty); + socket.emit("matchUpdate", { + status: "timeout", + message: "No match found within 30 seconds.", + }); + await redisClient.lRem( + `${topic}`, + 1, + JSON.stringify({ userId, difficulty }) + ); + }, 30000); + + const match = await findMatch(userId, topic, difficulty); + if (match) { + clearTimeout(socket.timeoutId); + const room_id = randomUUID(); + var temp_difficulty = difficulty; + if (temp_difficulty === null) { + temp_difficulty = "Easy"; + } + socket.emit("matchUpdate", { + status: "match_found", + userId: userId, + partnerId: match.userId, + roomId: room_id, + difficulty: temp_difficulty, + }); + const matchedSocket = findSocketByUserId(match.userId); + if (matchedSocket) { + clearTimeout(matchedSocket.timeoutId); + matchedSocket.emit("matchUpdate", { + status: "match_found", + userId: match.userId, + partnerId: userId, + roomId: room_id, + difficulty: temp_difficulty, + }); + } + await removeUser(userId, topic, difficulty); + } + }); + + socket.on("disconnect", async () => { + const { userId, topic, difficulty } = socket; + await removeUser(userId, topic, difficulty); + console.log(`Client disconnected: ${socket.id}`); + }); }); function findSocketByUserId(userId) { - // eslint-disable-next-line no-unused-vars - for (let [id, socket] of io.of("/").sockets) { - if (socket.userId === userId) { - return socket; - } + // eslint-disable-next-line no-unused-vars + for (let [id, socket] of io.of("/").sockets) { + if (socket.userId === userId) { + return socket; } - return null; + } + return null; } async function removeUser(userId, topic, difficulty) { - const user = '{"userId":"' + userId + '","difficulty":"' + difficulty + '"}' + const user = '{"userId":"' + userId + '","difficulty":"' + difficulty + '"}'; await redisClient.lRem(`${topic}`, 1, user); } async function findMatch(userId, topic, difficulty) { - const users = await redisClient.lRange(`${topic}`, 0, -1); - - for (const user of users) { - const parsedUser = JSON.parse(user); - if (parsedUser.userId !== userId && parsedUser.difficulty === difficulty) { - await redisClient.lRem(`${topic}`, 1, user); - return parsedUser; - } - } + const users = await redisClient.lRange(`${topic}`, 0, -1); - // If no difficulty match, match by topic - for (const user of users) { - const parsedUser = JSON.parse(user); - if (parsedUser.userId !== userId) { - await redisClient.lRem(`${topic}`, 1, user); - return parsedUser; - } + for (const user of users) { + const parsedUser = JSON.parse(user); + if (parsedUser.userId !== userId && parsedUser.difficulty === difficulty) { + await redisClient.lRem(`${topic}`, 1, user); + return parsedUser; + } + } + + // If no difficulty match, match by topic + for (const user of users) { + const parsedUser = JSON.parse(user); + if (parsedUser.userId !== userId) { + await redisClient.lRem(`${topic}`, 1, user); + return parsedUser; } + } - return null; + return null; } // Start WebSocket server server.listen(port, () => { - console.log("Matching service WebSocket listening on port " + port); + console.log("Matching service WebSocket listening on port " + port); }); From 0e21bb46bdd420fdb6b438e38d58d27b23b1b907 Mon Sep 17 00:00:00 2001 From: guowei42 <65711401+guowei42@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:04:03 +0800 Subject: [PATCH 2/2] fix cors endpoint --- server/matching-service/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/matching-service/server.js b/server/matching-service/server.js index 1d38960c38..0e6ef7bf8f 100644 --- a/server/matching-service/server.js +++ b/server/matching-service/server.js @@ -11,7 +11,7 @@ const server = http.createServer(); const io = new Server(server, { path: "/matching", cors: { - origin: true, + origin: ["http://localhost:3000", "https://peerprep-nine.vercel.app"], methods: "GET, POST, DELETE, PUT, PATCH", allowedHeaders: "Origin, X-Requested-With, Content-Type, Accept, Authorization, Cookie",