chore(core) Removed CLI access and Modified service names
All checks were successful
Docker Build and Push for Main Branch / docker (push) Successful in 2m14s
All checks were successful
Docker Build and Push for Main Branch / docker (push) Successful in 2m14s
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
FROM node:18-alpine
|
FROM nginx:stable-alpine
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/share/nginx/html
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
CMD ["node", "server.js"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
68
commands.js
68
commands.js
@@ -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,
|
|
||||||
};
|
|
||||||
12
index.html
12
index.html
@@ -31,25 +31,25 @@
|
|||||||
<th>Url</th>
|
<th>Url</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Dev Workspaces</td>
|
<td>Dev Spaces</td>
|
||||||
<td><a href="https://coder.phorge.fr" class="colorA">https://coder.phorge.fr</a></td>
|
<td><a href="https://coder.phorge.fr" class="colorA">https://coder.phorge.fr</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Monitoring</td>
|
<td>Monitoring</td>
|
||||||
<td><a href="https://monitoring.phorge.fr" class="colorA">https://monitoring.phorge.fr</a></td>
|
<td><a href="https://monitoring.phorge.fr" class="colorA">https://monitoring.phorge.fr</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>Status page</td>
|
|
||||||
<td><a href="https://status.phorge.fr/status" class="colorA">https://status.phorge.fr/status</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Git</td>
|
<td>Git</td>
|
||||||
<td><a href="https://git.phorge.fr" class="colorA">https://git.phorge.fr</a></td>
|
<td><a href="https://git.phorge.fr" class="colorA">https://git.phorge.fr</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>IaaS</td>
|
<td>Cloud Compute</td>
|
||||||
<td><a href="https://iaas.phorge.fr" class="colorA">https://iaas.phorge.fr</a></td>
|
<td><a href="https://iaas.phorge.fr" class="colorA">https://iaas.phorge.fr</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>AI Inference</td>
|
||||||
|
<td><a href="https://ai.phorge.fr" class="colorA">https://ai.phorge.fr</a></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
148
server.js
148
server.js
@@ -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}`);
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user