2017-05-11 12:53:16 -07:00
|
|
|
'use strict';
|
2017-10-24 10:05:49 +02:00
|
|
|
/* eslint-disable func-names */
|
2017-05-11 12:53:16 -07:00
|
|
|
|
|
|
|
|
// core requires
|
|
|
|
|
var http = require('http');
|
|
|
|
|
|
|
|
|
|
// external requires
|
|
|
|
|
var assert = require('chai').assert;
|
|
|
|
|
var restify = require('../../lib/index.js');
|
|
|
|
|
|
|
|
|
|
// local files
|
|
|
|
|
var helper = require('../lib/helper');
|
|
|
|
|
|
|
|
|
|
// local globals
|
|
|
|
|
var SERVER;
|
|
|
|
|
var PORT;
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
describe('multipart parser', function() {
|
|
|
|
|
beforeEach(function(done) {
|
2017-05-11 12:53:16 -07:00
|
|
|
SERVER = restify.createServer({
|
|
|
|
|
dtrace: helper.dtrace,
|
|
|
|
|
log: helper.getLog('server')
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
SERVER.get('/', function respond(req, res, next) {
|
|
|
|
|
res.send();
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
SERVER.listen(0, '127.0.0.1', function() {
|
2017-05-11 12:53:16 -07:00
|
|
|
PORT = SERVER.address().port;
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
afterEach(function(done) {
|
2017-05-11 12:53:16 -07:00
|
|
|
SERVER.close(done);
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
it('body multipart ok', function(done) {
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.queryParser({
|
|
|
|
|
mapParams: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.bodyParser({
|
|
|
|
|
mapParams: true
|
|
|
|
|
})
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
SERVER.post('/multipart/:id', function(req, res, next) {
|
|
|
|
|
assert.equal(req.params.id, 'foo');
|
|
|
|
|
assert.equal(req.params.mood, 'happy');
|
|
|
|
|
assert.equal(req.params.endorphins, '9000');
|
|
|
|
|
res.send();
|
|
|
|
|
next();
|
|
|
|
|
});
|
2017-05-11 12:53:16 -07:00
|
|
|
|
|
|
|
|
var opts = {
|
|
|
|
|
hostname: '127.0.0.1',
|
|
|
|
|
port: PORT,
|
|
|
|
|
path: '/multipart/foo?mood=happy',
|
|
|
|
|
agent: false,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data; boundary=huff'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
var client = http.request(opts, function(res) {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(res.statusCode, 200);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
client.write(
|
|
|
|
|
'--huff\r\nContent-Disposition: form-data; ' +
|
|
|
|
|
'name="endorphins"\r\n\r\n9000\r\n--huff--'
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
client.end();
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
it('gh-847 body multipart no files ok', function(done) {
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.queryParser({
|
|
|
|
|
mapParams: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.bodyParser({
|
|
|
|
|
mapFiles: true,
|
|
|
|
|
mapParams: true,
|
|
|
|
|
keepExtensions: true,
|
|
|
|
|
uploadDir: '/tmp/',
|
|
|
|
|
override: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
SERVER.post('/multipart/:id', function(req, res, next) {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(req.params.id, 'foo');
|
|
|
|
|
assert.equal(req.params.mood, 'happy');
|
|
|
|
|
assert.equal(req.params.endorphins, '9000');
|
|
|
|
|
res.send();
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var opts = {
|
|
|
|
|
hostname: '127.0.0.1',
|
|
|
|
|
port: PORT,
|
|
|
|
|
path: '/multipart/foo?mood=happy',
|
|
|
|
|
agent: false,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data; boundary=huff'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
var client = http.request(opts, function(res) {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(res.statusCode, 200);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// don't actually upload a file
|
2017-10-31 19:29:49 +01:00
|
|
|
client.write(
|
|
|
|
|
'--huff\r\nContent-Disposition: form-data; ' +
|
|
|
|
|
'name="endorphins"\r\n\r\n9000\r\n--huff--'
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
client.end();
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
it('gh-847 body multipart files ok', function(done) {
|
|
|
|
|
var shine =
|
|
|
|
|
'Well you wore out your welcome with random precision, ' +
|
2017-05-11 12:53:16 -07:00
|
|
|
'rode on the steel breeze. Come on you raver, you seer of ' +
|
|
|
|
|
'visions, come on you painter, you piper, you prisoner, and shine!';
|
2017-10-31 19:29:49 +01:00
|
|
|
var echoes =
|
|
|
|
|
'Overhead the albatross hangs motionless upon the air ' +
|
2017-05-11 12:53:16 -07:00
|
|
|
'And deep beneath the rolling waves in labyrinths of coral ' +
|
|
|
|
|
'caves The echo of a distant tide Comes willowing across the ' +
|
|
|
|
|
'sand And everything is green and submarine';
|
2017-10-31 19:29:49 +01:00
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.queryParser({
|
|
|
|
|
mapParams: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.bodyParser({
|
|
|
|
|
mapFiles: true,
|
|
|
|
|
mapParams: true,
|
|
|
|
|
keepExtensions: true,
|
|
|
|
|
uploadDir: '/tmp/',
|
|
|
|
|
override: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
SERVER.post('/multipart/:id', function(req, res, next) {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(req.params.id, 'foo');
|
|
|
|
|
assert.equal(req.params.mood, 'happy');
|
|
|
|
|
assert.equal(req.params.endorphins, '12');
|
|
|
|
|
assert.ok(req.params.shine);
|
|
|
|
|
assert.ok(req.params.echoes);
|
|
|
|
|
assert.equal(req.params.shine.toString('utf8'), shine);
|
|
|
|
|
assert.equal(req.params.echoes.toString('utf8'), echoes);
|
|
|
|
|
res.send();
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var opts = {
|
|
|
|
|
hostname: '127.0.0.1',
|
|
|
|
|
port: PORT,
|
|
|
|
|
path: '/multipart/foo?mood=happy',
|
|
|
|
|
agent: false,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data; boundary=huff'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
var client = http.request(opts, function(res) {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(res.statusCode, 200);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="endorphins"\r\n\r\n'
|
|
|
|
|
);
|
|
|
|
|
client.write('12\r\n');
|
|
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="shine"; ' +
|
|
|
|
|
'filename="shine.txt"\r\n'
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
client.write('Content-Type: text/plain\r\n\r\n');
|
|
|
|
|
client.write(shine + '\r\n');
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="echoes"; ' +
|
|
|
|
|
'filename="echoes.txt"\r\n'
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
client.write('Content-Type: text/plain\r\n\r\n');
|
|
|
|
|
client.write(echoes + '\r\n');
|
|
|
|
|
client.write('--huff--');
|
|
|
|
|
|
|
|
|
|
client.end();
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
it('body multipart ok custom handling', function(done) {
|
|
|
|
|
var detailsString =
|
|
|
|
|
'High endorphin levels make you happy. ' +
|
2017-05-11 12:53:16 -07:00
|
|
|
'Mostly... I guess. Whatever.';
|
2017-10-31 19:29:49 +01:00
|
|
|
SERVER.post(
|
|
|
|
|
'/multipart/:id',
|
2017-05-12 17:48:56 -07:00
|
|
|
restify.plugins.bodyParser({
|
2017-10-31 19:29:49 +01:00
|
|
|
multipartHandler: function(part) {
|
2017-05-11 12:53:16 -07:00
|
|
|
var buffer = new Buffer(0);
|
2017-10-31 19:29:49 +01:00
|
|
|
part.on('data', function(data) {
|
|
|
|
|
buffer = Buffer.concat([data]);
|
2017-05-11 12:53:16 -07:00
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
part.on('end', function() {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(part.name, 'endorphins');
|
|
|
|
|
assert.equal(buffer.toString('ascii'), '12');
|
|
|
|
|
});
|
|
|
|
|
},
|
2017-10-31 19:29:49 +01:00
|
|
|
multipartFileHandler: function(part) {
|
2017-05-11 12:53:16 -07:00
|
|
|
var buffer = new Buffer(0);
|
2017-10-31 19:29:49 +01:00
|
|
|
part.on('data', function(data) {
|
|
|
|
|
buffer = Buffer.concat([data]);
|
2017-05-11 12:53:16 -07:00
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
part.on('end', function() {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(part.name, 'details');
|
|
|
|
|
assert.equal(part.filename, 'mood_details.txt');
|
|
|
|
|
assert.equal(buffer.toString('ascii'), detailsString);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
mapParams: false
|
|
|
|
|
}),
|
2017-10-31 19:29:49 +01:00
|
|
|
function(req, res, next) {
|
2017-05-11 12:53:16 -07:00
|
|
|
res.send();
|
|
|
|
|
next();
|
2017-10-31 19:29:49 +01:00
|
|
|
}
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
|
|
|
|
|
var opts = {
|
|
|
|
|
hostname: '127.0.0.1',
|
|
|
|
|
port: PORT,
|
|
|
|
|
path: '/multipart/foo?mood=sad',
|
|
|
|
|
agent: false,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data; boundary=huff'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
var client = http.request(opts, function(res) {
|
2017-05-11 12:53:16 -07:00
|
|
|
assert.equal(res.statusCode, 200);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="endorphins"\r\n\r\n'
|
|
|
|
|
);
|
|
|
|
|
client.write('12\r\n');
|
|
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
|
|
|
|
|
// jscs:disable maximumLineLength
|
2017-10-31 19:29:49 +01:00
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="details"; ' +
|
|
|
|
|
'filename="mood_details.txt"\r\n'
|
|
|
|
|
);
|
2017-05-11 12:53:16 -07:00
|
|
|
|
|
|
|
|
// jscs:enable maximumLineLength
|
|
|
|
|
client.write('Content-Type: text/plain\r\n\r\n');
|
|
|
|
|
client.write(detailsString + '\r\n');
|
|
|
|
|
client.write('--huff--');
|
|
|
|
|
|
|
|
|
|
client.end();
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-31 19:29:49 +01:00
|
|
|
it('restify-GH-694 pass hash option through to Formidable', function(done) {
|
|
|
|
|
var content = 'Hello World!';
|
|
|
|
|
var hash = '2ef7bde608ce5404e97d5f042f95f89f1c232871';
|
|
|
|
|
SERVER.post(
|
|
|
|
|
'/multipart',
|
|
|
|
|
restify.plugins.bodyParser({ hash: 'sha1' }),
|
|
|
|
|
function(req, res, next) {
|
|
|
|
|
assert.equal(req.files.details.hash, hash);
|
|
|
|
|
res.send();
|
|
|
|
|
next();
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var opts = {
|
|
|
|
|
hostname: '127.0.0.1',
|
|
|
|
|
port: PORT,
|
|
|
|
|
path: '/multipart',
|
|
|
|
|
agent: false,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data; boundary=huff'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var client = http.request(opts, function(res) {
|
|
|
|
|
assert.equal(res.statusCode, 200);
|
|
|
|
|
done();
|
2017-10-20 08:23:57 +02:00
|
|
|
});
|
2017-10-31 19:29:49 +01:00
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
|
|
|
|
|
// jscs:disable maximumLineLength
|
|
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="details"; ' +
|
|
|
|
|
'filename="mood_details.txt"\r\n'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// jscs:enable maximumLineLength
|
|
|
|
|
client.write('Content-Type: text/plain\r\n\r\n');
|
|
|
|
|
client.write(content + '\r\n');
|
|
|
|
|
client.write('--huff--');
|
|
|
|
|
|
|
|
|
|
client.end();
|
|
|
|
|
});
|
2018-03-17 19:38:20 -04:00
|
|
|
|
|
|
|
|
it('Ensure maxFileSize change is enforced', function(done) {
|
|
|
|
|
var shine =
|
|
|
|
|
'Well you wore out your welcome with random precision, ' +
|
|
|
|
|
'rode on the steel breeze. Come on you raver, you seer of ' +
|
|
|
|
|
'visions, come on you painter, you piper, you prisoner, and shine!';
|
|
|
|
|
var echoes =
|
|
|
|
|
'Overhead the albatross hangs motionless upon the air ' +
|
|
|
|
|
'And deep beneath the rolling waves in labyrinths of coral ' +
|
|
|
|
|
'caves The echo of a distant tide Comes willowing across the ' +
|
|
|
|
|
'sand And everything is green and submarine';
|
|
|
|
|
|
|
|
|
|
var shortest = Math.min(shine.length, echoes.length);
|
|
|
|
|
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.queryParser({
|
|
|
|
|
mapParams: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
SERVER.use(
|
|
|
|
|
restify.plugins.bodyParser({
|
|
|
|
|
mapFiles: true,
|
|
|
|
|
mapParams: true,
|
|
|
|
|
keepExtensions: true,
|
|
|
|
|
uploadDir: '/tmp/',
|
|
|
|
|
override: true,
|
|
|
|
|
// Set limit to shortest of the 'files',
|
|
|
|
|
// longer will trigger an error.
|
|
|
|
|
maxFileSize: shortest
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
SERVER.post('/multipart/:id', function(req, res, next) {
|
|
|
|
|
assert.equal(req.params.id, 'foo');
|
|
|
|
|
assert.equal(req.params.mood, 'happy');
|
|
|
|
|
assert.equal(req.params.endorphins, '12');
|
|
|
|
|
assert.ok(req.params.shine);
|
|
|
|
|
assert.ok(req.params.echoes);
|
|
|
|
|
assert.equal(req.params.shine.toString('utf8'), shine);
|
|
|
|
|
assert.equal(req.params.echoes.toString('utf8'), echoes);
|
|
|
|
|
res.send();
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var opts = {
|
|
|
|
|
hostname: '127.0.0.1',
|
|
|
|
|
port: PORT,
|
|
|
|
|
path: '/multipart/foo?mood=happy',
|
|
|
|
|
agent: false,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data; boundary=huff'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var client = http.request(opts, function(res) {
|
|
|
|
|
assert.equal(res.statusCode, 400);
|
|
|
|
|
var body = '';
|
|
|
|
|
res.on('data', function(d) {
|
|
|
|
|
body += d;
|
|
|
|
|
});
|
|
|
|
|
res.on('end', function() {
|
|
|
|
|
var rsp = JSON.parse(body);
|
|
|
|
|
assert.equal(rsp.code, 'BadRequest');
|
|
|
|
|
assert.equal(
|
|
|
|
|
rsp.message.substring(0, 30),
|
|
|
|
|
'maxFileSize exceeded, received'
|
|
|
|
|
);
|
|
|
|
|
done();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="endorphins"\r\n\r\n'
|
|
|
|
|
);
|
|
|
|
|
client.write('12\r\n');
|
|
|
|
|
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
|
|
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="shine"; ' +
|
|
|
|
|
'filename="shine.txt"\r\n'
|
|
|
|
|
);
|
|
|
|
|
client.write('Content-Type: text/plain\r\n\r\n');
|
|
|
|
|
client.write(shine + '\r\n');
|
|
|
|
|
client.write('--huff\r\n');
|
|
|
|
|
|
|
|
|
|
client.write(
|
|
|
|
|
'Content-Disposition: form-data; name="echoes"; ' +
|
|
|
|
|
'filename="echoes.txt"\r\n'
|
|
|
|
|
);
|
|
|
|
|
client.write('Content-Type: text/plain\r\n\r\n');
|
|
|
|
|
client.write(echoes + '\r\n');
|
|
|
|
|
client.write('--huff--');
|
|
|
|
|
|
|
|
|
|
client.end();
|
|
|
|
|
});
|
2017-05-11 12:53:16 -07:00
|
|
|
});
|