Skip to content

Commit 56ae8f9

Browse files
Update server.js
1 parent 96c1688 commit 56ae8f9

File tree

1 file changed

+111
-42
lines changed

1 file changed

+111
-42
lines changed

server.js

Lines changed: 111 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import express from 'express';
2-
import { exec } from 'child_process';
2+
// import cors from 'cors';
3+
import { exec as rawExec } from 'child_process';
4+
import util from 'util';
35
import fs from 'fs';
46
import { fileURLToPath } from 'url';
57
import path from 'path';
68

9+
710
// Simulate __dirname
811
const __filename = fileURLToPath(import.meta.url);
912
const __dirname = path.dirname(__filename);
1013

1114
const app = express();
12-
app.use(express.json());
13-
15+
// app.use(express.json());
16+
app.use(express.json({ limit: '256kb' }));
17+
const exec = util.promisify(rawExec);
1418
// Define paths for pre-created files
1519
const tempDir = path.join(__dirname, 'temp');
1620
const languageConfigs = {
@@ -161,60 +165,125 @@ app.get('/',(req,res)=>{
161165
// });
162166

163167

164-
app.post(['/execute', '/submit-code'], async (req, res) => {
165-
const { code, language } = req.body;
166-
if (!languageConfigs[language]) {
167-
return res.status(400).json({ error: 'Unsupported language' });
168-
}
168+
// app.post(['/execute', '/submit-code'], async (req, res) => {
169+
// const { code, language } = req.body;
170+
// if (!languageConfigs[language]) {
171+
// return res.status(400).json({ error: 'Unsupported language' });
172+
// }
173+
174+
// const { filePath } = languageConfigs[language];
175+
// fs.writeFileSync(filePath, code);
176+
177+
// let command = '';
178+
// const filename = path.basename(filePath);
179+
180+
// switch (language) {
181+
// case 'cpp':
182+
// command = `/usr/bin/time -f "Execution Time: %e seconds\nMemory Used: %M KB" g++ ${filePath} -o ${tempDir}/a.out && ${tempDir}/a.out`;
183+
// break;
184+
// case 'python':
185+
// command = `python3 ${filePath}`;
186+
// break;
187+
// case 'js':
188+
// command = `node ${filePath}`;
189+
// break;
190+
// case 'java':
191+
// const className = filename.replace('.java', '');
192+
// command = `javac ${filePath} && java -cp ${tempDir} ${className}`;
193+
// break;
194+
// default:
195+
// return res.status(400).json({ error: 'Unsupported language' });
196+
// }
197+
198+
// exec(command, (err, stdout, stderr) => {
199+
// if (err || stderr.includes('error')) {
200+
// return res.status(400).json({
201+
// error: stderr.split('\n')
202+
// .filter(line => !line.includes('Execution Time') && !line.includes('Memory Used'))
203+
// .join('\n').trim(),
204+
// output: 'Test case 1: Failed',
205+
// });
206+
// }
169207

170-
const { filePath } = languageConfigs[language];
171-
fs.writeFileSync(filePath, code);
208+
// const executionTime = (stderr.match(/Execution Time: (.+?) seconds/) || [])[1] || 'N/A';
209+
// const memoryUsage = (stderr.match(/Memory Used: (.+?) KB/) || [])[1] || 'N/A';
172210

173-
let command = '';
174-
const filename = path.basename(filePath);
211+
// res.status(200).json({
212+
// output: stdout.trim(),
213+
// executionTime,
214+
// memoryUsage,
215+
// });
216+
// });
217+
// });
175218

219+
/* ---------- helpers ---------- */
220+
function buildCommand(filePath, language) {
176221
switch (language) {
177222
case 'cpp':
178-
command = `/usr/bin/time -f "Execution Time: %e seconds\nMemory Used: %M KB" g++ ${filePath} -o ${tempDir}/a.out && ${tempDir}/a.out`;
179-
break;
223+
return `/usr/bin/time -f "Execution Time: %e seconds\nMemory Used: %M KB" \
224+
g++ ${filePath} -o ${tempDir}/a.out && ${tempDir}/a.out`;
180225
case 'python':
181-
command = `python3 ${filePath}`;
182-
break;
226+
return `python3 ${filePath}`;
183227
case 'js':
184-
command = `node ${filePath}`;
185-
break;
186-
case 'java':
187-
const className = filename.replace('.java', '');
188-
command = `javac ${filePath} && java -cp ${tempDir} ${className}`;
189-
break;
228+
return `node ${filePath}`;
229+
case 'java': {
230+
const className = path.basename(filePath, '.java');
231+
return `javac ${filePath} && java -cp ${tempDir} ${className}`;
232+
}
190233
default:
191-
return res.status(400).json({ error: 'Unsupported language' });
234+
throw new Error('Unsupported language');
192235
}
236+
}
237+
238+
const pick = (s, re) => (s.match(re) || [])[1] || 'N/A';
239+
const clean = s =>
240+
s.split('\n')
241+
.filter(l => !/Execution Time|Memory Used/.test(l))
242+
.join('\n')
243+
.trim();
244+
245+
/* ---------- ONE handler used by both endpoints ---------- */
246+
async function runCode(req, res) {
247+
const { code = '', language = '' } = req.body || {};
248+
249+
/* 1. validate language ------------------------------------------------ */
250+
const cfg = languageConfigs[language];
251+
if (!cfg) return res.status(400).json({ error: 'Unsupported language' });
252+
253+
/* 2. write code to its temp file -------------------------------------- */
254+
await fs.promises.mkdir(tempDir, { recursive: true });
255+
await fs.promises.writeFile(cfg.filePath, code);
256+
257+
/* 3. build the shell command ----------------------------------------- */
258+
const cmd = buildCommand(cfg.filePath, language);
259+
260+
/* 4. exec with hard limits ------------------------------------------- */
261+
try {
262+
const { stdout, stderr } = await exec(cmd, {
263+
timeout: 10_000, // ⏱️ kill after 10 s
264+
maxBuffer: 1_048_576 // 1 MiB stdout+stderr
265+
});
193266

194-
exec(command, (err, stdout, stderr) => {
195-
if (err || stderr.includes('error')) {
196-
return res.status(400).json({
197-
error: stderr.split('\n')
198-
.filter(line => !line.includes('Execution Time') && !line.includes('Memory Used'))
199-
.join('\n').trim(),
200-
output: 'Test case 1: Failed',
201-
});
202-
}
203-
204-
const executionTime = (stderr.match(/Execution Time: (.+?) seconds/) || [])[1] || 'N/A';
205-
const memoryUsage = (stderr.match(/Memory Used: (.+?) KB/) || [])[1] || 'N/A';
206-
207-
res.status(200).json({
267+
return res.json({
208268
output: stdout.trim(),
209-
executionTime,
210-
memoryUsage,
269+
executionTime: pick(stderr, /Execution Time:\s*(.+?)\s*seconds/),
270+
memoryUsage: pick(stderr, /Memory Used:\s*(.+?)\s*KB/)
211271
});
212-
});
213-
});
272+
} catch (err) {
273+
/* timeout → err.killed === true, compile/runtime error → err.code */
274+
const status = err.killed ? 408 : 400;
275+
const stderr = err.stderr || err.message || '';
276+
return res.status(status).json({ error: clean(stderr) });
277+
}
278+
}
214279

280+
/* ---------- the two routes ------------------------------------------- */
281+
app.post('/execute', runCode);
282+
app.post('/submit-code', runCode);
215283

216284

217-
const PORT = 8080;
285+
// const PORT = 8080;
286+
const PORT = process.env.PORT || 8080;
218287
app.listen(PORT, '0.0.0.0', () =>
219288
console.log(`Server listening on ${PORT}`)
220289
);

0 commit comments

Comments
 (0)