Skip to content

Commit 612e7a6

Browse files
committed
Check for empty post data
1 parent 8ab92aa commit 612e7a6

File tree

3 files changed

+63
-27
lines changed

3 files changed

+63
-27
lines changed

src/routes/compile.js

+24-12
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,43 @@ const BUILD_TIMEOUT = process.env.BUILD_TIMEOUT || 10000;
1818
const router = express.Router();
1919
const queueMw = expressQueue({ activeLimit: 1, queuedLimit: 20 });
2020

21+
/** Utility function to convert script->exe */
22+
async function compileScript(id, script) {
23+
try {
24+
await fs.writeFile(`/tmp/${id}.ahk`, script);
25+
26+
await new Promise(async (resolve) => {
27+
proc.exec(`xvfb-run -a wine Ahk2Exe.exe /in /tmp/${id}.ahk`, { timeout: BUILD_TIMEOUT }, (err, stout, sterr) => {
28+
resolve(err ? stout : sterr);
29+
});
30+
});
31+
32+
return await fs.readFile(`/tmp/${id}.exe`);
33+
} finally {
34+
await del(`/tmp/${id}.*`, { force: true });
35+
}
36+
}
37+
2138
router.post('/', queueMw, async (req, res) => {
39+
if (!req.body) {
40+
res.status(400).send({ error: { code: -1, message: 'Empty body' } });
41+
return;
42+
}
43+
2244
const id = md5(req.body);
2345

2446
let data = mcache.get(id);
2547
if (!data) {
2648
console.log(`processing uncached:${id}`);
2749

2850
try {
29-
await fs.writeFile(`/tmp/${id}.ahk`, req.body);
30-
31-
await new Promise(async (resolve) => {
32-
proc.exec(`xvfb-run -a wine Ahk2Exe.exe /in /tmp/${id}.ahk`, { timeout: BUILD_TIMEOUT }, (err, stout, sterr) => {
33-
resolve(err ? stout : sterr);
34-
});
35-
});
36-
37-
data = await fs.readFile(`/tmp/${id}.exe`);
51+
data = await compileScript(id, req.body);
3852

3953
mcache.put(id, data, CACHE_TIMEOUT);
4054
} catch (err) {
4155
console.error(err.message);
42-
res.status(400).send({ error: { code: err.code || -1, message: err.message || 'unknown' } });
56+
res.status(500).send({ error: { code: err.code || -1, message: err.message || 'unknown' } });
4357
return;
44-
} finally {
45-
await del(`/tmp/${id}.*`, { force: true });
4658
}
4759
}
4860

test/e2e.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import server from '../src/app';
66
chai.should();
77
chai.use(chaiHttp);
88

9-
describe('Status endpoint', () => {
9+
describe('IT::Status endpoint', () => {
1010
it('should report zero when idle', (done) => {
1111
chai.request(server).get('/status')
1212
.end((err, res) => {

test/routes/compile.js

+38-14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import httpMocks from 'node-mocks-http';
44
import { promises as fs } from 'fs';
55
import proc from 'child_process';
66
import sinon from 'sinon';
7+
import ee from 'events';
78
import compile from '../../src/routes/compile';
89

910
chai.should();
@@ -14,10 +15,11 @@ return
1415
`;
1516
const ID = '3ab771baa15b807fc028f9766eb111b0';
1617

17-
describe('Compile route', () => {
18+
describe('Compile endpoint', () => {
1819
let exec;
1920
let fswriteFile;
2021
let fsreadFile;
22+
2123
beforeEach(() => {
2224
fswriteFile = sinon.stub(fs, 'writeFile');
2325
fsreadFile = sinon.stub(fs, 'readFile').returns(Buffer.from('<EXE DATA>'));
@@ -28,31 +30,53 @@ describe('Compile route', () => {
2830
sinon.restore();
2931
});
3032

33+
it('should reject a empty request', (done) => {
34+
const res = httpMocks.createResponse({
35+
eventEmitter: ee.EventEmitter,
36+
});
37+
const req = httpMocks.createRequest({
38+
method: 'POST',
39+
url: '/',
40+
body: '',
41+
});
42+
// TODO: undo bodge with body producing {}
43+
req.body = '';
44+
45+
res.once('end', () => {
46+
res.statusCode.should.equal(400);
47+
48+
done();
49+
});
50+
51+
compile.router.handle(req, res);
52+
});
53+
3154
it('should convert a valid request', (done) => {
32-
const response = httpMocks.createResponse();
33-
const request = httpMocks.createRequest({
55+
const res = httpMocks.createResponse({
56+
eventEmitter: ee.EventEmitter,
57+
});
58+
const req = httpMocks.createRequest({
3459
method: 'POST',
3560
url: '/',
3661
body: SCRIPT,
3762
});
3863

39-
// TODO: use for negative test case
40-
// response.on('end', () => {
41-
// response._getData().should.equal('world');
42-
// done();
43-
// });
64+
res.sendFileBuffer = (name, data) => {
65+
name.should.be.equal(`${ID}.exe`);
66+
data.should.be.instanceof(Buffer);
67+
68+
// boilerplate to behave as real express middleware
69+
res.status(200).send();
70+
};
4471

45-
response.sendFileBuffer = (name, data) => {
72+
res.once('end', () => {
4673
sinon.assert.calledWith(fswriteFile, `/tmp/${ID}.ahk`, SCRIPT);
4774
sinon.assert.calledWith(exec, `xvfb-run -a wine Ahk2Exe.exe /in /tmp/${ID}.ahk`);
4875
sinon.assert.calledWith(fsreadFile, `/tmp/${ID}.exe`);
4976

50-
name.should.be.equal(`${ID}.exe`);
51-
data.should.be.instanceof(Buffer);
52-
5377
done();
54-
};
78+
});
5579

56-
compile.router.handle(request, response);
80+
compile.router.handle(req, res);
5781
});
5882
});

0 commit comments

Comments
 (0)