mirror of https://github.com/lukechilds/node.git
Felix Geisendörfer
15 years ago
committed by
Ryan Dahl
2 changed files with 213 additions and 0 deletions
@ -0,0 +1,162 @@ |
|||
exports.Stream = function(options) { |
|||
node.EventEmitter.call(this); |
|||
|
|||
this.init(options); |
|||
}; |
|||
node.inherits(exports.Stream, node.EventEmitter); |
|||
|
|||
|
|||
var proto = exports.Stream.prototype; |
|||
|
|||
proto.init = function(options) { |
|||
this.buffer = ''; |
|||
this.bytesReceived = 0; |
|||
this.bytesTotal = 0; |
|||
this.part = null; |
|||
|
|||
if ('headers' in options) { |
|||
var req = options, contentType = req.headers['Content-Type']; |
|||
if (contentType) { |
|||
contentType = contentType.split(/; ?boundary=/) |
|||
this.boundary = '--'+contentType[1]; |
|||
} |
|||
|
|||
this.bytesTotal = req.headers['Content-Length']; |
|||
|
|||
var self = this; |
|||
req |
|||
.addListener('body', function(chunk) { |
|||
req.pause(); |
|||
self.write(chunk); |
|||
setTimeout(function() { |
|||
req.resume(); |
|||
}); |
|||
}) |
|||
.addListener('complete', function() { |
|||
self.emit('complete'); |
|||
}); |
|||
} else { |
|||
this.boundary = options.boundary; |
|||
} |
|||
}; |
|||
|
|||
proto.write = function(chunk) { |
|||
this.bytesReceived = this.bytesReceived + chunk.length; |
|||
this.buffer = this.buffer + chunk; |
|||
|
|||
while (this.buffer.length) { |
|||
var offset = this.buffer.indexOf(this.boundary); |
|||
|
|||
if (offset === 0) { |
|||
this.buffer = this.buffer.substr(offset + this.boundary.length + 2); |
|||
} else if (offset == -1) { |
|||
if (this.buffer === "\r\n") { |
|||
this.buffer = ''; |
|||
} else { |
|||
this.part = (this.part || new Part(this)); |
|||
this.part.write(this.buffer); |
|||
this.buffer = []; |
|||
} |
|||
} else if (offset > 0) { |
|||
this.part = (this.part || new Part(this)); |
|||
this.part.write(this.buffer.substr(0, offset - 2)); |
|||
|
|||
this.part.emit('complete'); |
|||
|
|||
this.part = new Part(this); |
|||
this.buffer = this.buffer.substr(offset + this.boundary.length + 2); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
function Part(stream) { |
|||
node.EventEmitter.call(this); |
|||
|
|||
this.headers = {}; |
|||
this.buffer = ''; |
|||
this.bytesReceived = 0; |
|||
|
|||
// Avoids turning Part into a circular JSON object
|
|||
this.getStream = function() { |
|||
return stream; |
|||
}; |
|||
|
|||
this._headersComplete = false; |
|||
} |
|||
node.inherits(Part, node.EventEmitter); |
|||
|
|||
Part.prototype.parsedHeaders = function() { |
|||
for (var header in this.headers) { |
|||
var parts = this.headers[header].split(/; ?/), parsedHeader = {}; |
|||
for (var i = 0; i < parts.length; i++) { |
|||
var pair = parts[i].split('='); |
|||
if (pair.length < 2) { |
|||
continue; |
|||
} |
|||
|
|||
var key = pair[0].toLowerCase(), val = pair[1] || ''; |
|||
val = stripslashes(val).substr(1); |
|||
val = val.substr(0, val.length - 1); |
|||
|
|||
parsedHeader[key] = val; |
|||
} |
|||
this.headers[header] = parsedHeader; |
|||
} |
|||
}; |
|||
|
|||
Part.prototype.write = function(chunk) { |
|||
if (this._headersComplete) { |
|||
this.bytesReceived = this.bytesReceived + chunk.length; |
|||
this.emit('body', chunk); |
|||
return; |
|||
} |
|||
|
|||
this.buffer = this.buffer + chunk; |
|||
while (this.buffer.length) { |
|||
var offset = this.buffer.indexOf("\r\n"); |
|||
|
|||
if (offset === 0) { |
|||
this._headersComplete = true; |
|||
this.parsedHeaders(); |
|||
this.getStream().emit('part', this); |
|||
|
|||
this.buffer = this.buffer.substr(2); |
|||
this.bytesReceived = this.bytesReceived + this.buffer.length; |
|||
this.emit('body', this.buffer); |
|||
return; |
|||
} else if (offset > 0) { |
|||
var header = this.buffer.substr(0, offset).split(/: ?/); |
|||
this.headers[header[0]] = header[1]; |
|||
this.buffer = this.buffer.substr(offset+2); |
|||
} else if (offset === false) { |
|||
return; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
function stripslashes(str) { |
|||
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
|||
// + improved by: Ates Goral (http://magnetiq.com)
|
|||
// + fixed by: Mick@el
|
|||
// + improved by: marrtins
|
|||
// + bugfixed by: Onno Marsman
|
|||
// + improved by: rezna
|
|||
// + input by: Rick Waldron
|
|||
// + reimplemented by: Brett Zamir (http://brett-zamir.me)
|
|||
// * example 1: stripslashes('Kevin\'s code');
|
|||
// * returns 1: "Kevin's code"
|
|||
// * example 2: stripslashes('Kevin\\\'s code');
|
|||
// * returns 2: "Kevin\'s code"
|
|||
return (str+'').replace(/\\(.?)/g, function (s, n1) { |
|||
switch(n1) { |
|||
case '\\': |
|||
return '\\'; |
|||
case '0': |
|||
return '\0'; |
|||
case '': |
|||
return ''; |
|||
default: |
|||
return n1; |
|||
} |
|||
}); |
|||
} |
@ -0,0 +1,51 @@ |
|||
include("common.js"); |
|||
|
|||
var multipart = require('/multipart.js'); |
|||
var port = 8222; |
|||
var parts_reveived = 0; |
|||
var parts_complete = 0; |
|||
var parts = {}; |
|||
|
|||
var server = node.http.createServer(function(req, res) { |
|||
var stream = new multipart.Stream(req); |
|||
|
|||
stream.addListener('part', function(part) { |
|||
parts_reveived++; |
|||
|
|||
var name = part.headers['Content-Disposition'].name; |
|||
|
|||
if (parts_reveived == 1) { |
|||
assertEquals('test-field', name); |
|||
} else if (parts_reveived == 2) { |
|||
assertEquals('test-file', name); |
|||
} |
|||
|
|||
parts[name] = ''; |
|||
part.addListener('body', function(chunk) { |
|||
parts[name] += chunk; |
|||
}); |
|||
part.addListener('complete', function(chunk) { |
|||
if (parts_reveived == 1) { |
|||
assertEquals('foobar', parts[name]); |
|||
} else if (parts_reveived == 2) { |
|||
assertEquals(node.fs.cat(__filename).wait(), parts[name]); |
|||
} |
|||
parts_complete++; |
|||
}); |
|||
}); |
|||
|
|||
stream.addListener('complete', function() { |
|||
res.sendHeader(200, {"Content-Type": "text/plain"}); |
|||
res.sendBody('thanks'); |
|||
res.finish(); |
|||
server.close(); |
|||
}); |
|||
}); |
|||
server.listen(port); |
|||
|
|||
var cmd = 'curl -H "Expect:" -F "test-field=foobar" -F test-file=@'+__filename+' http://localhost:'+port+'/'; |
|||
var result = node.exec(cmd).wait(); |
|||
|
|||
process.addListener('exit', function() { |
|||
assertEquals(2, parts_complete); |
|||
}); |
Loading…
Reference in new issue