Skip to content

Commit

Permalink
Merge pull request #53 from CS3219-AY2425S1/fix-cors
Browse files Browse the repository at this point in the history
Fix cors
  • Loading branch information
guowei42 authored Nov 13, 2024
2 parents 2fd83a0 + 0e21bb4 commit 617dac6
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 89 deletions.
8 changes: 4 additions & 4 deletions api-gateway/api.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion client/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

# API endpoints
# without port
REACT_APP_API_BASE_URL=http://localhost
REACT_APP_API_BASE_URL=http://localhost
39 changes: 29 additions & 10 deletions client/src/socket.js
Original file line number Diff line number Diff line change
@@ -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
})
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,
});
1 change: 1 addition & 0 deletions server/chat-service/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions server/collaboration-service/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
170 changes: 96 additions & 74 deletions server/matching-service/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
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);
});

0 comments on commit 617dac6

Please sign in to comment.