Skip to content

Commit b688b66

Browse files
authored
use the new multipartparser which is a stream
1 parent 214708a commit b688b66

File tree

1 file changed

+93
-88
lines changed

1 file changed

+93
-88
lines changed

lib/incoming_form.js

Lines changed: 93 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -344,98 +344,103 @@ IncomingForm.prototype._initMultipart = function(boundary) {
344344

345345
parser.initWithBoundary(boundary);
346346

347-
parser.onPartBegin = function() {
348-
part = new Stream();
349-
part.readable = true;
350-
part.headers = {};
351-
part.name = null;
352-
part.filename = null;
353-
part.mime = null;
354-
355-
part.transferEncoding = 'binary';
356-
part.transferBuffer = '';
357-
358-
headerField = '';
359-
headerValue = '';
360-
};
361-
362-
parser.onHeaderField = (b, start, end) => {
363-
headerField += b.toString(this.encoding, start, end);
364-
};
365-
366-
parser.onHeaderValue = (b, start, end) => {
367-
headerValue += b.toString(this.encoding, start, end);
368-
};
369-
370-
parser.onHeaderEnd = () => {
371-
headerField = headerField.toLowerCase();
372-
part.headers[headerField] = headerValue;
373-
374-
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
375-
var m = headerValue.match(/\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i);
376-
if (headerField == 'content-disposition') {
377-
if (m) {
378-
part.name = m[2] || m[3] || '';
379-
}
347+
parser.on('data', ({name, buffer, start, end}) => {
348+
if (name === 'partBegin') {
349+
part = new Stream();
350+
part.readable = true;
351+
part.headers = {};
352+
part.name = null;
353+
part.filename = null;
354+
part.mime = null;
355+
356+
part.transferEncoding = 'binary';
357+
part.transferBuffer = '';
358+
359+
headerField = '';
360+
headerValue = '';
361+
} else if (name === 'headerField') {
362+
headerField += buffer.toString(this.encoding, start, end);
363+
} else if (name === 'headerValue') {
364+
headerValue += buffer.toString(this.encoding, start, end);
365+
} else if (name === 'headerEnd') {
366+
headerField = headerField.toLowerCase();
367+
part.headers[headerField] = headerValue;
368+
369+
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
370+
var m = headerValue.match(/\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i);
371+
if (headerField == 'content-disposition') {
372+
if (m) {
373+
part.name = m[2] || m[3] || '';
374+
}
380375

381-
part.filename = this._fileName(headerValue);
382-
} else if (headerField == 'content-type') {
383-
part.mime = headerValue;
384-
} else if (headerField == 'content-transfer-encoding') {
385-
part.transferEncoding = headerValue.toLowerCase();
386-
}
376+
part.filename = this._fileName(headerValue);
377+
} else if (headerField == 'content-type') {
378+
part.mime = headerValue;
379+
} else if (headerField == 'content-transfer-encoding') {
380+
part.transferEncoding = headerValue.toLowerCase();
381+
}
387382

388-
headerField = '';
389-
headerValue = '';
390-
};
383+
headerField = '';
384+
headerValue = '';
385+
} else if (name === 'headersEnd') {
386+
387+
switch(part.transferEncoding){
388+
case 'binary':
389+
case '7bit':
390+
case '8bit': {
391+
const dataPropagation = ({name, buffer, start, end}) => {
392+
if (name === 'partData') {
393+
part.emit('data', buffer.slice(start, end));
394+
}
395+
};
396+
const dataStopPropagation = ({name}) => {
397+
if (name === 'partEnd') {
398+
part.emit('end');
399+
parser.off('data', dataPropagation);
400+
parser.off('data', dataStopPropagation);
401+
}
402+
};
403+
parser.on('data', dataPropagation);
404+
parser.on('data', dataStopPropagation);
405+
break;
406+
} case 'base64': {
407+
const dataPropagation = ({name, buffer, start, end}) => {
408+
if (name === 'partData') {
409+
part.transferBuffer += buffer.slice(start, end).toString('ascii');
410+
411+
/*
412+
four bytes (chars) in base64 converts to three bytes in binary
413+
encoding. So we should always work with a number of bytes that
414+
can be divided by 4, it will result in a number of buytes that
415+
can be divided vy 3.
416+
*/
417+
var offset = parseInt(part.transferBuffer.length / 4, 10) * 4;
418+
part.emit('data', Buffer.from(part.transferBuffer.substring(0, offset), 'base64'));
419+
part.transferBuffer = part.transferBuffer.substring(offset);
420+
}
421+
};
422+
const dataStopPropagation = ({name}) => {
423+
if (name === 'partEnd') {
424+
part.emit('data', Buffer.from(part.transferBuffer, 'base64'));
425+
part.emit('end');
426+
parser.off('data', dataPropagation);
427+
parser.off('data', dataStopPropagation);
428+
}
429+
};
430+
parser.on('data', dataPropagation);
431+
parser.on('data', dataStopPropagation);
432+
break;
433+
434+
} default:
435+
return this._error(new Error('unknown transfer-encoding'));
436+
}
391437

392-
parser.onHeadersEnd = () => {
393-
switch(part.transferEncoding){
394-
case 'binary':
395-
case '7bit':
396-
case '8bit':
397-
parser.onPartData = function(b, start, end) {
398-
part.emit('data', b.slice(start, end));
399-
};
400-
401-
parser.onPartEnd = function() {
402-
part.emit('end');
403-
};
404-
break;
405-
406-
case 'base64':
407-
parser.onPartData = function(b, start, end) {
408-
part.transferBuffer += b.slice(start, end).toString('ascii');
409-
410-
/*
411-
four bytes (chars) in base64 converts to three bytes in binary
412-
encoding. So we should always work with a number of bytes that
413-
can be divided by 4, it will result in a number of buytes that
414-
can be divided vy 3.
415-
*/
416-
var offset = parseInt(part.transferBuffer.length / 4, 10) * 4;
417-
part.emit('data', Buffer.from(part.transferBuffer.substring(0, offset), 'base64'));
418-
part.transferBuffer = part.transferBuffer.substring(offset);
419-
};
420-
421-
parser.onPartEnd = function() {
422-
part.emit('data', Buffer.from(part.transferBuffer, 'base64'));
423-
part.emit('end');
424-
};
425-
break;
426-
427-
default:
428-
return this._error(new Error('unknown transfer-encoding'));
438+
this.onPart(part);
439+
} else if (name === 'end') {
440+
this.ended = true;
441+
this._maybeEnd();
429442
}
430-
431-
this.onPart(part);
432-
};
433-
434-
435-
parser.onEnd = () => {
436-
this.ended = true;
437-
this._maybeEnd();
438-
};
443+
});
439444

440445
this._parser = parser;
441446
};

0 commit comments

Comments
 (0)