2021-01-14 20:14:26 +01:00
|
|
|
const { writeFile } = require('fs/promises');
|
|
|
|
const express = require('express');
|
|
|
|
const app = express();
|
|
|
|
const languages = require('./languages');
|
2021-01-14 21:06:26 +01:00
|
|
|
const { spawn } = require('child_process');
|
2021-01-14 20:14:26 +01:00
|
|
|
|
2021-01-14 21:06:26 +01:00
|
|
|
(function setVersions() {
|
|
|
|
let output = '';
|
2021-01-14 20:14:26 +01:00
|
|
|
|
2021-01-14 21:06:26 +01:00
|
|
|
const process = spawn(__dirname + '/../../lxc/versions');
|
2021-01-14 20:14:26 +01:00
|
|
|
|
2021-01-14 21:06:26 +01:00
|
|
|
process.stdout.setEncoding('utf-8');
|
|
|
|
process.stderr.setEncoding('utf-8');
|
2021-01-14 20:14:26 +01:00
|
|
|
|
2021-01-14 21:06:26 +01:00
|
|
|
process.stdout.addListener('data', chunk => {
|
|
|
|
output += chunk;
|
|
|
|
});
|
|
|
|
|
|
|
|
process.stderr.addListener('data', chunk => {
|
|
|
|
output += chunk;
|
|
|
|
});
|
|
|
|
|
|
|
|
process.on('exit', () => {
|
|
|
|
const sections = output.toLowerCase().split('---');
|
|
|
|
const versions = {};
|
|
|
|
|
|
|
|
for (let section of sections) {
|
|
|
|
section = section.trim().split('\n');
|
|
|
|
|
|
|
|
if (section.length >= 2) {
|
|
|
|
const language = section[0];
|
|
|
|
|
|
|
|
versions[language] = /\d.\d.\d/.exec(section.slice(1).join('\n'))?.[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const language of languages) {
|
|
|
|
language.version = versions[language.name];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
})();
|
2021-01-14 20:14:26 +01:00
|
|
|
|
|
|
|
app.use(express.json());
|
|
|
|
|
|
|
|
app.post('/execute', (req, res) => {
|
|
|
|
const body = req.body;
|
|
|
|
|
|
|
|
const language = languages.find(language => {
|
|
|
|
return language.aliases.includes(body.language?.toString()?.toLowerCase());
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!language) {
|
|
|
|
return res.status(400).json({
|
|
|
|
code: 'unsupported_language',
|
|
|
|
message: `${body.language} is not supported by Piston`,
|
|
|
|
});
|
2021-01-14 20:25:45 +01:00
|
|
|
} else if (typeof body.source !== 'string') {
|
2021-01-14 20:14:26 +01:00
|
|
|
return res.status(400).json({
|
|
|
|
code: 'missing_source',
|
|
|
|
message: 'source field is invalid',
|
|
|
|
});
|
2021-01-14 20:26:41 +01:00
|
|
|
} else if (body.args && !Array.isArray(body.args)) {
|
2021-01-14 20:14:26 +01:00
|
|
|
return res.status(400).json({
|
|
|
|
code: 'invalid_args',
|
|
|
|
message: 'args field is not an array',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
launch(res, language, body);
|
|
|
|
});
|
|
|
|
|
|
|
|
async function launch(res, language, body) {
|
|
|
|
const stamp = new Date().getTime();
|
|
|
|
const sourceFile = `/tmp/${stamp}.code`;
|
|
|
|
|
|
|
|
await writeFile(sourceFile, body.source);
|
|
|
|
|
|
|
|
const process = spawn(__dirname + '/../../lxc/execute', [language.name, sourceFile, (body.args ?? []).join('\n')]);
|
|
|
|
|
|
|
|
const result = {
|
|
|
|
ran: true,
|
|
|
|
language: language.name,
|
|
|
|
stderr: '',
|
|
|
|
stdout: '',
|
|
|
|
output: '',
|
|
|
|
};
|
|
|
|
|
|
|
|
if (language.version)
|
|
|
|
result.version = language.version;
|
|
|
|
|
|
|
|
process.stderr.setEncoding('utf-8');
|
|
|
|
process.stdout.setEncoding('utf-8');
|
|
|
|
|
|
|
|
process.stderr.addListener('data', chunk => {
|
|
|
|
result.stderr += chunk;
|
|
|
|
result.output += chunk;
|
|
|
|
});
|
|
|
|
|
|
|
|
process.stdout.addListener('data', chunk => {
|
|
|
|
result.stdout += chunk;
|
|
|
|
result.output += chunk;
|
|
|
|
});
|
|
|
|
|
|
|
|
result.stderr = result.stderr.substring(0, 65535);
|
|
|
|
result.stdout = result.stdout.substring(0, 65535);
|
|
|
|
result.output = result.output.substring(0, 65535);
|
|
|
|
|
|
|
|
process.on('exit', () => {
|
|
|
|
res.json(result);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
app.get('/versions', (req, res) => {
|
|
|
|
res.json(languages);
|
|
|
|
});
|
|
|
|
|
|
|
|
const PORT = 2000;
|
|
|
|
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
|