diff --git a/Dockerfile b/Dockerfile index dfee474..9a34b59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -FROM node:18-alpine +FROM nginx:stable-alpine -WORKDIR /usr/src/app +WORKDIR /usr/share/nginx/html COPY . . EXPOSE 80 -CMD ["node", "server.js"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/commands.js b/commands.js deleted file mode 100644 index e916ebf..0000000 --- a/commands.js +++ /dev/null @@ -1,68 +0,0 @@ -const services = [ - { name: 'Dev Workspaces', url: 'https://coder.phorge.fr' }, - { name: 'Monitoring', url: 'https://monitoring.phorge.fr' }, - { name: 'Status page', url: 'https://status.phorge.fr/status' }, - { name: 'Git', url: 'https://git.phorge.fr' }, - { name: 'IaaS', url: 'https://iaas.phorge.fr' }, -]; - -const commands = [ - { - names: ['/services'], - description: 'Displays available services', - execute: (socket) => { - socket.write('Available services:\r\n'); - for (const service of services) { - socket.write(`- ${service.name}: ${service.url}\r\n`); - } - }, - }, - { - names: ['/help', 'help'], - description: 'Displays command help', - execute: (socket) => { - socket.write('Available commands:\r\n'); - for (const command of commands) { - socket.write(`- ${command.names[0]}: ${command.description}\r\n`); - } - }, - }, - { - names: ['/exit', 'quit'], - description: 'Exits the terminal session', - execute: (socket) => { - socket.write('Goodbye.\r\n'); - socket.end(); - }, - }, -]; - -const resolveCommand = (input) => { - const normalized = input.trim().toLowerCase(); - return commands.find((command) => command.names.includes(normalized)); -}; - -const handleCommand = (socket, input) => { - const trimmed = input.trim(); - if (!trimmed) { - socket.write('phorge> '); - return; - } - - const command = resolveCommand(trimmed); - if (command) { - command.execute(socket); - if (command.names.includes('/exit') || command.names.includes('quit')) { - return; - } - } else { - socket.write(`Unknown command : ${trimmed}\r\n`); - socket.write('Type /help for assistance.\r\n'); - } - - socket.write('phorge> '); -}; - -module.exports = { - handleCommand, -}; diff --git a/index.html b/index.html index 6b61f04..b46a6df 100644 --- a/index.html +++ b/index.html @@ -31,25 +31,25 @@ Url - Dev Workspaces + Dev Spaces https://coder.phorge.fr Monitoring https://monitoring.phorge.fr - - Status page - https://status.phorge.fr/status - Git https://git.phorge.fr - IaaS + Cloud Compute https://iaas.phorge.fr + + AI Inference + https://ai.phorge.fr + \ No newline at end of file diff --git a/server.js b/server.js deleted file mode 100644 index 4813a42..0000000 --- a/server.js +++ /dev/null @@ -1,148 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const net = require('net'); -const { handleCommand } = require('./commands'); - -const asciiLogo = ` + **==+= === - ===+ %========= +====== ++* =*==+ =====+=+=== ++====*+ - ===+ === +=== ============ ==========* ==========- ============ - ===+ %=== +=== ===* ==== ====+ === +=== %=== +=== - ===# %=== ==== ===* ===# ===+ *==# === === ===* -%=== %=== ==== #=== ==== === ==+ === %==+*********==== - ===# %=== +=== -==+ *=== ==+ +=== *===# *================ - ===+ %=== ====* #=== ==== ==+ ========+ %==+ - ====+ %=== +===+ ===* ===# ==+ === === - *=============== *==== ==== ==+ ===+ *===+ ===* - =*======*+ ============# ==+ ============+ ============% - %=== =+====++ **# ===+= ===++==== =*====++ - %=== === === - %=== ===+ ==== - %=== =============== - *======= `; - -const contentTypes = { - '.html': 'text/html; charset=utf-8', - '.css': 'text/css; charset=utf-8', - '.js': 'application/javascript; charset=utf-8', - '.svg': 'image/svg+xml', - '.png': 'image/png', - '.jpg': 'image/jpeg', - '.jpeg': 'image/jpeg', - '.ico': 'image/x-icon', - '.json': 'application/json; charset=utf-8', -}; - -const buildPath = (requestedPath) => { - let safePath = requestedPath.split('?')[0].split('#')[0]; - safePath = decodeURIComponent(safePath); - safePath = safePath.replace(/^\//, ''); - if (!safePath || safePath === '') { - return path.join(__dirname, 'index.html'); - } - - const candidate = path.join(__dirname, safePath); - if (!candidate.startsWith(__dirname)) { - return null; - } - return candidate; -}; - -const isHttpRequest = (chunk) => { - return /^(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH|TRACE|CONNECT)\s+/i.test(chunk); -}; - -const sendHttpResponse = (socket, statusCode, statusText, headers, body) => { - const head = [`HTTP/1.1 ${statusCode} ${statusText}`]; - for (const [key, value] of Object.entries(headers)) { - head.push(`${key}: ${value}`); - } - head.push('Connection: close'); - head.push(''); - if (body) { - socket.end(head.join('\r\n') + '\r\n' + body); - } else { - socket.end(head.join('\r\n') + '\r\n'); - } -}; - -const handleHttp = (socket, requestData) => { - const [requestLine] = requestData.split('\r\n'); - const [method, requestPath] = requestLine.split(' '); - const filePath = buildPath(requestPath); - - if (!filePath) { - return sendHttpResponse(socket, 400, 'Bad Request', { 'Content-Type': 'text/plain; charset=utf-8' }, '400 Bad Request'); - } - - fs.stat(filePath, (err, stats) => { - if (err || !stats.isFile()) { - return sendHttpResponse(socket, 404, 'Not Found', { 'Content-Type': 'text/plain; charset=utf-8' }, '404 Not Found'); - } - - fs.readFile(filePath, (readErr, data) => { - if (readErr) { - return sendHttpResponse(socket, 500, 'Internal Server Error', { 'Content-Type': 'text/plain; charset=utf-8' }, '500 Internal Server Error'); - } - - const ext = path.extname(filePath).toLowerCase(); - const contentType = contentTypes[ext] || 'application/octet-stream'; - sendHttpResponse(socket, 200, 'OK', { 'Content-Type': contentType, 'Content-Length': Buffer.byteLength(data) }, data); - }); - }); -}; - -const createTerminalSession = (socket, initialData) => { - socket.write(asciiLogo + '\r\n\r\n'); - socket.write('Open-Source & Community first Cloud Provider (/help for assistance)\r\n'); - socket.write('phorge> '); - - let buffer = ''; - if (initialData) { - buffer += initialData; - } - - const flushLines = () => { - let index; - while ((index = buffer.indexOf('\n')) !== -1) { - let line = buffer.slice(0, index).replace(/\r$/, ''); - buffer = buffer.slice(index + 1); - handleCommand(socket, line); - } - }; - - socket.on('data', (chunk) => { - buffer += chunk.toString('utf8'); - flushLines(); - }); - - socket.on('error', () => { - socket.destroy(); - }); -}; - -const server = net.createServer((socket) => { - socket.setEncoding('utf8'); - let hasHandled = false; - - const onFirstData = (chunk) => { - if (hasHandled) return; - hasHandled = true; - const data = chunk.toString('utf8'); - if (isHttpRequest(data)) { - handleHttp(socket, data); - } else { - createTerminalSession(socket, data); - } - }; - - socket.once('data', onFirstData); - - socket.on('error', () => { - socket.destroy(); - }); -}); - -const PORT = process.env.PORT || 80; -server.listen(PORT, () => { - console.log(`Phorge server listening on port ${PORT}`); -});