mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Merge pull request #163 from ets-cfuhrman-pfe/nginx-port-forward
Nginx port forward
This commit is contained in:
commit
2df750b6f7
11 changed files with 257 additions and 51 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Socket } from 'socket.io-client';
|
import { io,Socket } from 'socket.io-client';
|
||||||
//import { ENV_VARIABLES } from '../../../constants';
|
//import { ENV_VARIABLES } from '../../../constants';
|
||||||
|
|
||||||
import StudentModeQuiz from '../../../components/StudentModeQuiz/StudentModeQuiz';
|
import StudentModeQuiz from '../../../components/StudentModeQuiz/StudentModeQuiz';
|
||||||
|
|
@ -34,7 +34,15 @@ const JoinRoom: React.FC = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleCreateSocket = () => {
|
const handleCreateSocket = () => {
|
||||||
const socket = webSocketService.connect("localhost:4500");
|
debugger;
|
||||||
|
const socket = io('/', {
|
||||||
|
path: `/api/room/${roomName}/socket`,
|
||||||
|
transports: ['websocket'],
|
||||||
|
autoConnect: true,
|
||||||
|
reconnection: true,
|
||||||
|
reconnectionAttempts: 5,
|
||||||
|
reconnectionDelay: 1000,
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('join-success', () => {
|
socket.on('join-success', () => {
|
||||||
setIsWaitingForTeacher(true);
|
setIsWaitingForTeacher(true);
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,10 @@ const ManageRoom: React.FC = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createWebSocketRoom = () => {
|
const createWebSocketRoom = async() => {
|
||||||
setConnectingError('');
|
setConnectingError('');
|
||||||
const socket = webSocketService.connect("localhost:4500");
|
const room = await(await fetch('/api/room',{method:'post'})).json();
|
||||||
|
const socket = webSocketService.connect(`/api/room/${room.id}/socket`);
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
webSocketService.createRoom();
|
webSocketService.createRoom();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,69 @@
|
||||||
FROM nginx
|
# Stage 1: Build stage
|
||||||
|
FROM nginx:1.27-alpine AS builder
|
||||||
|
|
||||||
COPY ./default.conf /etc/nginx/conf.d/default.conf
|
# Install required packages
|
||||||
|
RUN apk add --no-cache nginx-mod-http-js nginx-mod-http-keyval
|
||||||
|
|
||||||
|
# Stage 2: Final stage
|
||||||
|
FROM alpine:3.19
|
||||||
|
|
||||||
|
# Copy Nginx and NJS modules from builder
|
||||||
|
COPY --from=builder /usr/sbin/nginx /usr/sbin/
|
||||||
|
COPY --from=builder /usr/lib/nginx/modules/ /usr/lib/nginx/modules/
|
||||||
|
COPY --from=builder /etc/nginx/ /etc/nginx/
|
||||||
|
COPY --from=builder /usr/lib/nginx/ /usr/lib/nginx/
|
||||||
|
|
||||||
|
# Install required runtime dependencies
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
pcre2 \
|
||||||
|
ca-certificates \
|
||||||
|
pcre \
|
||||||
|
libgcc \
|
||||||
|
libstdc++ \
|
||||||
|
zlib \
|
||||||
|
libxml2 \
|
||||||
|
libedit \
|
||||||
|
geoip \
|
||||||
|
libxslt \
|
||||||
|
&& mkdir -p /var/cache/nginx \
|
||||||
|
&& mkdir -p /var/log/nginx \
|
||||||
|
&& mkdir -p /etc/nginx/conf.d \
|
||||||
|
&& mkdir -p /etc/nginx/njs \
|
||||||
|
&& ln -sf /dev/stdout /var/log/nginx/access.log \
|
||||||
|
&& ln -sf /dev/stderr /var/log/nginx/error.log \
|
||||||
|
&& addgroup -S nginx \
|
||||||
|
&& adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx
|
||||||
|
|
||||||
|
# Copy necessary libraries from builder
|
||||||
|
COPY --from=builder /usr/lib/libxml2.so* /usr/lib/
|
||||||
|
COPY --from=builder /usr/lib/libexslt.so* /usr/lib/
|
||||||
|
COPY --from=builder /usr/lib/libgd.so* /usr/lib/
|
||||||
|
COPY --from=builder /usr/lib/libxslt.so* /usr/lib/
|
||||||
|
|
||||||
|
# Modify nginx.conf to load modules
|
||||||
|
RUN echo 'load_module modules/ngx_http_js_module.so;' > /tmp/nginx.conf && \
|
||||||
|
cat /etc/nginx/nginx.conf >> /tmp/nginx.conf && \
|
||||||
|
mv /tmp/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
# Copy our configuration
|
||||||
|
COPY conf.d/default.conf /etc/nginx/conf.d/
|
||||||
|
COPY njs/main.js /etc/nginx/njs/
|
||||||
|
|
||||||
|
# Set proper permissions
|
||||||
|
RUN chown -R nginx:nginx /var/cache/nginx \
|
||||||
|
&& chown -R nginx:nginx /var/log/nginx \
|
||||||
|
&& chown -R nginx:nginx /etc/nginx/conf.d \
|
||||||
|
&& touch /var/run/nginx.pid \
|
||||||
|
&& chown -R nginx:nginx /var/run/nginx.pid
|
||||||
|
|
||||||
|
# Verify the configuration
|
||||||
|
# RUN nginx -t --dry-run
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nginx
|
||||||
|
|
||||||
|
# Expose HTTP port
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Start Nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
59
nginx/conf.d/default.conf
Normal file
59
nginx/conf.d/default.conf
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
js_import njs/main.js;
|
||||||
|
|
||||||
|
map $http_upgrade $connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream frontend {
|
||||||
|
server frontend:5173;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream backend {
|
||||||
|
server backend:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
set $proxy_target "";
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
proxy_pass http://backend;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game WebSocket routing
|
||||||
|
location ~/api/room/([^/]+)/socket {
|
||||||
|
set $room_id $1;
|
||||||
|
js_content main.routeWebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
# WebSocket proxy location
|
||||||
|
location @websocket_proxy {
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
||||||
|
# Timeouts
|
||||||
|
proxy_connect_timeout 7m;
|
||||||
|
proxy_send_timeout 7m;
|
||||||
|
proxy_read_timeout 7m;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
proxy_pass $proxy_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://frontend;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
nginx/conf.d/local.conf
Normal file
60
nginx/conf.d/local.conf
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
js_import njs/main.js;
|
||||||
|
js_set $quiz_room_host main.getQuizRoomHost;
|
||||||
|
|
||||||
|
map $http_upgrade $connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache for room information
|
||||||
|
# keyval_zone zone=rooms:10m;
|
||||||
|
# keyval_zone zone=room_hosts:10m;
|
||||||
|
# keyval $room_id $room_info zone=rooms;
|
||||||
|
|
||||||
|
upstream frontend {
|
||||||
|
server localhost:5173;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream backend {
|
||||||
|
server localhost:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
rewrite /backend/(.*) /$1 break;
|
||||||
|
proxy_pass http://backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /socket.io {
|
||||||
|
rewrite /backend/(.*) /$1 break;
|
||||||
|
proxy_pass http://backend;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_hide_header 'Access-Control-Allow-Origin';
|
||||||
|
}
|
||||||
|
|
||||||
|
location /quiz/([^/]+)/socket {
|
||||||
|
# Routing logic
|
||||||
|
set $room_id $1;
|
||||||
|
js_content main.routeWebSocket;
|
||||||
|
|
||||||
|
#Proxy headers
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://frontend;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
upstream frontend {
|
|
||||||
server frontend:5173;
|
|
||||||
}
|
|
||||||
|
|
||||||
upstream backend {
|
|
||||||
server backend:3000;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
location /api {
|
|
||||||
rewrite /backend/(.*) /$1 break;
|
|
||||||
proxy_pass http://backend;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /socket.io {
|
|
||||||
rewrite /backend/(.*) /$1 break;
|
|
||||||
proxy_pass http://backend;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_hide_header 'Access-Control-Allow-Origin';
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://frontend;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
54
nginx/njs/main.js
Normal file
54
nginx/njs/main.js
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
async function fetchRoomInfo(r) {
|
||||||
|
try {
|
||||||
|
// Make request to API to get room info
|
||||||
|
let res = await r.subrequest('/api/room/' + r.variables.room_id, {
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status !== 200) {
|
||||||
|
r.error(`Failed to fetch room info: ${res.status}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let room = JSON.parse(res.responseText);
|
||||||
|
r.error(`Debug: Room info: ${JSON.stringify(room)}`); // Debug log
|
||||||
|
return room;
|
||||||
|
} catch (error) {
|
||||||
|
r.error(`Error fetching room info: ${error}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function routeWebSocket(r) {
|
||||||
|
try {
|
||||||
|
const roomInfo = await fetchRoomInfo(r);
|
||||||
|
|
||||||
|
if (!roomInfo || !roomInfo.host) {
|
||||||
|
r.error(`Debug: Invalid room info: ${JSON.stringify(roomInfo)}`);
|
||||||
|
r.return(404, 'Room not found or invalid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the host includes protocol if not already present
|
||||||
|
let proxyUrl = roomInfo.host;
|
||||||
|
if (!proxyUrl.startsWith('http://') && !proxyUrl.startsWith('https://')) {
|
||||||
|
proxyUrl = 'http://' + proxyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.error(`Debug: Original URL: ${r.uri}`);
|
||||||
|
r.error(`Debug: Setting proxy target to: ${proxyUrl}`);
|
||||||
|
r.error(`Debug: Headers: ${JSON.stringify(r.headersIn)}`);
|
||||||
|
|
||||||
|
// Set the proxy target variable
|
||||||
|
r.variables.proxy_target = proxyUrl;
|
||||||
|
|
||||||
|
// Redirect to the websocket proxy
|
||||||
|
r.internalRedirect('@websocket_proxy');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
r.error(`WebSocket routing error: ${error}`);
|
||||||
|
r.return(500, 'Internal routing error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { routeWebSocket };
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Use the Node base image
|
# Use the Node base image
|
||||||
FROM node:18 as quizroom
|
FROM node:18 AS quizroom
|
||||||
|
|
||||||
# Create a working directory
|
# Create a working directory
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ const port = 4500;
|
||||||
// Create HTTP and WebSocket server
|
// Create HTTP and WebSocket server
|
||||||
const server = http.createServer();
|
const server = http.createServer();
|
||||||
const ioOptions: Partial<ServerOptions> = {
|
const ioOptions: Partial<ServerOptions> = {
|
||||||
path: "/socket.io",
|
path: '/api/room/975239/socket', // TODO : use env variable to set room id
|
||||||
cors: {
|
cors: {
|
||||||
origin: "*",
|
origin: "*",
|
||||||
methods: ["GET", "POST"],
|
methods: ["GET", "POST"],
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ const DockerRoomProvider = require('../roomsProviders/docker-provider.js');
|
||||||
//const KubernetesRoomProvider = require('../roomsProviders/kubernetes-provider');
|
//const KubernetesRoomProvider = require('../roomsProviders/kubernetes-provider');
|
||||||
|
|
||||||
const NB_CODE_CHARS = 6;
|
const NB_CODE_CHARS = 6;
|
||||||
const DEFAULT_HOST = "localhost:4500"
|
const DEFAULT_HOST = "172.18.0.5:4500" // must be room ip not name
|
||||||
|
|
||||||
class RoomsController {
|
class RoomsController {
|
||||||
constructor(options = {}, roomRepository) {
|
constructor(options = {}, roomRepository) {
|
||||||
|
|
|
||||||
|
|
@ -42,15 +42,6 @@ router.delete("/:id", async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/:id", async (req, res) => {
|
router.get("/:id", async (req, res) => {
|
||||||
try {
|
|
||||||
const data = await roomsController.getRoomStatus();
|
|
||||||
res.json(data);
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: "Failed to join rooms" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get("/:id/status", async (req, res) => {
|
|
||||||
try {
|
try {
|
||||||
const data = await roomsController.getRoomStatus(req.params.id);
|
const data = await roomsController.getRoomStatus(req.params.id);
|
||||||
res.json(data);
|
res.json(data);
|
||||||
|
|
@ -59,6 +50,4 @@ router.get("/:id/status", async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue