Skip to content

Commit 266c10d

Browse files
committed
Massive overhauls. Adding Travis C.I. build. FINALLY have testing!!! Added linting rules to keep the project clean.
1 parent 92d7ad5 commit 266c10d

16 files changed

+1392
-60
lines changed

.eslintrc

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"extends": "google",
3+
"env": {
4+
"node": true,
5+
"mocha": true
6+
},
7+
"parserOptions": {
8+
"ecmaVersion": 6
9+
},
10+
"rules": {
11+
"comma-dangle": [2, "never"],
12+
"max-len": [2, {
13+
"code": 100,
14+
"tabWidth": 2
15+
}]
16+
}
17+
}

.gitignore

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ npm-debug.log
1010
node_modules
1111
*.log
1212
*.gz
13-
test/uploadedfiles/*
14-
!test/uploadedfiles/placeholder.txt
13+
14+
test/uploads
15+
test/manual/uploads/*
16+
!test/manual/uploads/placeholder.txt

.travis.yml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
sudo: false
2+
language: node_js
3+
node_js:
4+
- "4"
5+
- "5"
6+
- "6"
7+
- "7"
8+
script:
9+
- npm test
10+
- npm run lint

README.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
# Description
22
Simple express middleware for uploading files.
33

4-
# Version 0.1.0 Breaking Change
5-
As of `v0.1.0`, there is NO MORE `application/x-www-form-urlencoded` SUPPORT!
4+
# Version 0.1.0 Breaking Changes
5+
6+
## BREAKING CHANGE: No more urlencoded support
7+
As of `v0.1.0`, there is NO MORE `application/x-www-form-urlencoded` SUPPORT! Moving forward, express-fileupload is considered a "multipart" solution only.
68

79
If you want to parse `urlencoded` requests, [use body-parser](https://github.com/expressjs/body-parser#bodyparserurlencodedoptions).
810

9-
Moving forward, express-fileupload is considered a "multipart" solution only.
11+
## BREAKING CHANGE: Official support for Node v4.x.x +
12+
Use with lower versions of Node at your own risk!
1013

1114
# Install
1215
```bash

lib/index.js

+23-24
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
var Busboy = require('busboy');
2-
var fs = require('fs-extra');
3-
var streamifier = require('streamifier');
1+
'use strict';
42

5-
var ACCEPTABLE_MIME = /^(?:multipart\/.+)$/i;
6-
var UNACCEPTABLE_METHODS = [
3+
const Busboy = require('busboy');
4+
const fs = require('fs-extra');
5+
const streamifier = require('streamifier');
6+
7+
const ACCEPTABLE_MIME = /^(?:multipart\/.+)$/i;
8+
const UNACCEPTABLE_METHODS = [
79
'GET',
810
'HEAD'
911
];
@@ -19,7 +21,6 @@ module.exports = function(options) {
1921
};
2022
};
2123

22-
2324
/**
2425
* Processes multipart request
2526
* Builds a req.body object for fields
@@ -31,14 +32,16 @@ module.exports = function(options) {
3132
* @return {void}
3233
*/
3334
function processMultipart(options, req, res, next) {
34-
var busboyOptions = {};
35-
var busboy;
35+
let busboyOptions = {};
36+
let busboy;
3637

3738
req.files = null;
3839

3940
// Build busboy config
40-
for (var k in options) {
41-
busboyOptions[k] = options[k];
41+
for (let k in options) {
42+
if (Object.prototype.hasOwnProperty.call(options, k)) {
43+
busboyOptions[k] = options[k];
44+
}
4245
}
4346

4447
// Attach request headers to busboy config
@@ -51,7 +54,7 @@ function processMultipart(options, req, res, next) {
5154
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mime) {
5255
req.body = req.body || {};
5356

54-
var prev = req.body[fieldname];
57+
let prev = req.body[fieldname];
5558

5659
if (!prev)
5760
return req.body[fieldname] = val;
@@ -64,8 +67,8 @@ function processMultipart(options, req, res, next) {
6467

6568
// Build req.files fields
6669
busboy.on('file', function(fieldname, file, filename, encoding, mime) {
67-
var buf = new Buffer(0);
68-
var safeFileNameRegex = /[^\w-]/g;
70+
let buf = new Buffer(0);
71+
let safeFileNameRegex = /[^\w-]/g;
6972

7073
file.on('data', function(data) {
7174
buf = Buffer.concat([buf, data]);
@@ -77,11 +80,11 @@ function processMultipart(options, req, res, next) {
7780
file.on('end', function() {
7881
if (!req.files)
7982
req.files = {};
80-
83+
8184
// see: https://github.com/richardgirges/express-fileupload/issues/14
8285
// firefox uploads empty file in case of cache miss when f5ing page.
8386
// resulting in unexpected behavior. if there is no file data, the file is invalid.
84-
if(!buf.length)
87+
if(!buf.length)
8588
return;
8689

8790
if (options.safeFileNames) {
@@ -91,13 +94,13 @@ function processMultipart(options, req, res, next) {
9194
filename = filename.replace(safeFileNameRegex, '');
9295
}
9396

94-
var newFile = {
97+
let newFile = {
9598
name: filename,
9699
data: buf,
97100
encoding: encoding,
98101
mimetype: mime,
99102
mv: function(path, callback) {
100-
var fstream = fs.createWriteStream(path);
103+
let fstream = fs.createWriteStream(path);
101104

102105
streamifier.createReadStream(buf).pipe(fstream);
103106

@@ -131,11 +134,7 @@ function processMultipart(options, req, res, next) {
131134
req.pipe(busboy);
132135
}
133136

134-
135-
/**************************************************************
136-
* Methods below were copied from, or heavily inspired by
137-
* the Connect and connect-busboy packages
138-
**************************************************************/
137+
// Methods below were copied from, or heavily inspired by the Connect and connect-busboy packages
139138

140139
/**
141140
* Ensures the request is not using a non-compliant multipart method
@@ -153,7 +152,7 @@ function hasAcceptableMethod(req) {
153152
* @return {Boolean}
154153
*/
155154
function hasAcceptableMime(req) {
156-
var str = (req.headers['content-type'] || '').split(';')[0];
155+
let str = (req.headers['content-type'] || '').split(';')[0];
157156

158157
return ACCEPTABLE_MIME.test(str);
159158
}
@@ -166,4 +165,4 @@ function hasAcceptableMime(req) {
166165
function hasBody(req) {
167166
return ('transfer-encoding' in req.headers) ||
168167
('content-length' in req.headers && req.headers['content-length'] !== '0');
169-
}
168+
}

package.json

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
{
22
"name": "express-fileupload",
3-
"version": "0.1.0-beta",
3+
"version": "0.1.0",
44
"author": "Richard Girges <[email protected]>",
55
"description": "Simple express file upload middleware that wraps around Busboy",
66
"main": "./lib/index",
7+
"scripts": {
8+
"test": "mocha \"test/**/*.spec.js\"",
9+
"lint": "eslint ./"
10+
},
711
"dependencies": {
812
"busboy": "^0.2.14",
913
"fs-extra": "^0.22.1",
1014
"streamifier": "^0.1.1"
1115
},
1216
"engines": {
13-
"node": ">=0.8.0"
17+
"node": ">=4.0.0"
1418
},
1519
"keywords": [
1620
"express",
@@ -22,14 +26,14 @@
2226
"busboy",
2327
"middleware"
2428
],
25-
"licenses": [
26-
{
27-
"type": "MIT",
28-
"url": "https://github.com/richardgirges/express-fileupload/raw/master/LICENSE"
29-
}
30-
],
29+
"license": "MIT",
3130
"repository": "richardgirges/express-fileupload",
3231
"devDependencies": {
33-
"express": "^4.13.4"
32+
"body-parser": "^1.16.1",
33+
"eslint": "^3.15.0",
34+
"eslint-config-google": "^0.7.1",
35+
"express": "^4.13.4",
36+
"mocha": "^3.2.0",
37+
"supertest": "^3.0.0"
3438
}
3539
}

test/files/basketball.png

151 KB
Loading

test/files/car.png

263 KB
Loading

test/files/tree.png

265 KB
Loading
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
var express = require('express'),
2-
fileUpload = require('../lib/index.js'),
3-
app = express();
1+
const express = require('express');
2+
const fileUpload = require('../../lib/index.js');
3+
const app = express();
44

5-
app.use('/form', express.static(__dirname + '/upload.test.html'));
5+
app.use('/form', express.static(__dirname + '/index.html'));
66

77
// default options
88
app.use(fileUpload());
@@ -12,7 +12,8 @@ app.get('/ping', function(req, res) {
1212
});
1313

1414
app.post('/upload', function(req, res) {
15-
var sampleFile, uploadPath;
15+
let sampleFile;
16+
let uploadPath;
1617

1718
if (!req.files) {
1819
res.status(400).send('No files were uploaded.');
@@ -23,18 +24,16 @@ app.post('/upload', function(req, res) {
2324

2425
sampleFile = req.files.sampleFile;
2526

26-
uploadPath = __dirname + '/uploadedfiles/' + sampleFile.name;
27+
uploadPath = __dirname + '/uploads/' + sampleFile.name;
2728

2829
sampleFile.mv(uploadPath, function(err) {
29-
if (err) {
30-
res.status(500).send(err);
31-
}
32-
else {
33-
res.send('File uploaded to ' + uploadPath);
34-
}
30+
if (err)
31+
return res.status(500).send(err);
32+
33+
res.send('File uploaded to ' + uploadPath);
3534
});
3635
});
3736

3837
app.listen(8000, function() {
3938
console.log('Express server listening on port 8000');
40-
})
39+
});

test/multipartFields.spec.js

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'use strict';
2+
3+
const request = require('supertest');
4+
5+
const {
6+
app
7+
} = require('./server');
8+
9+
let mockUser = {
10+
firstName: 'Joe',
11+
lastName: 'Schmo',
12+
13+
};
14+
15+
let mockCars = [
16+
'rsx',
17+
'tsx',
18+
'civic',
19+
'integra'
20+
];
21+
22+
describe('Test Multipart Form Single Field Submissions', function() {
23+
it('submit multipart user data with POST', function(done) {
24+
request(app)
25+
.post('/fields/user')
26+
.field('firstName', mockUser.firstName)
27+
.field('lastName', mockUser.lastName)
28+
.field('email', mockUser.email)
29+
.expect('Content-Type', /json/)
30+
.expect(200, {
31+
firstName: mockUser.firstName,
32+
lastName: mockUser.lastName,
33+
email: mockUser.email
34+
}, done);
35+
});
36+
37+
it('submit multipart user data with PUT', function(done) {
38+
request(app)
39+
.post('/fields/user')
40+
.field('firstName', mockUser.firstName)
41+
.field('lastName', mockUser.lastName)
42+
.field('email', mockUser.email)
43+
.expect('Content-Type', /json/)
44+
.expect(200, {
45+
firstName: mockUser.firstName,
46+
lastName: mockUser.lastName,
47+
email: mockUser.email
48+
}, done);
49+
});
50+
51+
it('fail when user data submitted without multipart', function(done) {
52+
request(app)
53+
.post('/fields/user')
54+
.send(mockUser)
55+
.expect(400)
56+
.end(done);
57+
});
58+
59+
it('fail when user data not submitted', function(done) {
60+
request(app)
61+
.post('/fields/user')
62+
.expect(400)
63+
.end(done);
64+
});
65+
});
66+
67+
describe('Test Multipart Form Array Field Submissions', function() {
68+
it('submit array of data with POST', function(done) {
69+
let req = request(app).post('/fields/array');
70+
71+
for (let i = 0; i < mockCars.length; i++) {
72+
req.field('testField', mockCars[i]);
73+
}
74+
75+
req
76+
.expect(200)
77+
.end(function(err, res) {
78+
if (err)
79+
return done(err);
80+
81+
let responseMatchesRequest = res.body.join(',') === mockCars.join(',');
82+
83+
done(responseMatchesRequest ? null : 'Data was returned as expected.');
84+
});
85+
});
86+
});

0 commit comments

Comments
 (0)