Skip to content

Commit

Permalink
refactor connect-file-transfer to work with event emitter
Browse files Browse the repository at this point in the history
  • Loading branch information
marty-wang committed Dec 4, 2011
1 parent b788053 commit 70066d9
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 128 deletions.
99 changes: 43 additions & 56 deletions lib/connect-file-transfer.js
@@ -1,72 +1,59 @@
(function() {
var fs, parse, path, _callback, _cb, _fileTransferer, _root, _transfer;
var fs, parse, path;

fs = require("fs");

parse = require("url").parse;

path = require('path');

/* Private
*/

_root = null;

_callback = null;

_fileTransferer = null;

_cb = function(error, payload) {
if (_callback != null) {
return process.nextTick(function() {
return _callback(error, payload);
});
}
};

_transfer = function(req, res, next) {
var filepath, pathname;
pathname = parse(req.url).pathname;
filepath = path.join(_root, pathname);
return _fileTransferer.transfer(filepath, function(err, payload) {
if (err != null) {
_cb(err, pathname);
return next();
} else {
switch (payload.status) {
case 'start':
_cb(null, {
status: 'start',
pathname: pathname
});
return res.writeHead(200, {
'Content-Type': payload.contentType
});
case 'transfer':
return res.write(payload.content);
case 'complete':
res.end(payload.content);
return _cb(null, {
status: "complete",
pathname: pathname
});
}
exports.connect = function(fileTransferer, root, callback) {
var asyncCallback, nextFn, pathname, req, res;
req = null;
res = null;
nextFn = null;
pathname = null;
asyncCallback = function(error, payload) {
if (callback != null) {
return process.nextTick(function() {
return callback(error, payload);
});
}
};
fileTransferer.on('error', function(error) {
asyncCallback(error, pathname);
return nextFn();
});
};

/* Public
*/

exports.connect = function(fileTransferer, root, callback) {
_root = root;
_callback = callback;
_fileTransferer = fileTransferer;
return function(req, res, next) {
fileTransferer.on('start', function(data) {
res.writeHead(200, {
'Content-Type': data
});
return asyncCallback(null, {
status: 'start',
pathname: pathname
});
});
fileTransferer.on('transfer', function(data) {
return res.write(data);
});
fileTransferer.on('complete', function(data) {
res.end(data);
return asyncCallback(null, {
status: "complete",
pathname: pathname
});
});
return function(request, response, next) {
var filepath;
req = request;
res = response;
nextFn = next;
switch (req.method.toUpperCase()) {
case "GET":
case "POST":
return _transfer(req, res, next);
pathname = parse(req.url).pathname;
filepath = path.join(root, pathname);
return fileTransferer.transfer(filepath);
default:
return next();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/file-transfer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 41 additions & 45 deletions src/connect-file-transfer.coffee
Expand Up @@ -2,54 +2,50 @@ fs = require "fs"
parse = require("url").parse
path = require 'path'

### Private ###

_root = null
_callback = null
_fileTransferer = null

_cb = (error, payload) ->
process.nextTick(->
_callback error, payload
) if _callback?

_transfer = (req, res, next) ->
pathname = parse(req.url).pathname
filepath = path.join _root, pathname

_fileTransferer.transfer filepath, (err, payload) ->
if err?
_cb err, pathname
next()
else
switch payload.status
when 'start'
_cb null, {
status: 'start'
pathname: pathname
}
res.writeHead 200, {
'Content-Type': payload.contentType
}
when 'transfer'
res.write payload.content
when 'complete'
res.end payload.content
_cb null, {
status: "complete"
pathname: pathname
}

### Public ###

exports.connect = (fileTransferer, root, callback) ->
_root = root
_callback = callback
_fileTransferer = fileTransferer
req = null
res = null
nextFn = null
pathname = null

asyncCallback = (error, payload) ->
process.nextTick(->
callback error, payload
) if callback?

fileTransferer.on 'error', (error) ->
asyncCallback error, pathname
nextFn()

fileTransferer.on 'start', (data) ->
res.writeHead 200, {
'Content-Type': data
}
asyncCallback null, {
status: 'start'
pathname: pathname
}

fileTransferer.on 'transfer', (data) ->
res.write data

fileTransferer.on 'complete', (data) ->
res.end data
asyncCallback null, {
status: "complete"
pathname: pathname
}

(request, response, next) ->
req = request
res = response
nextFn = next

(req, res, next) ->
switch req.method.toUpperCase()
when "GET", "POST"
_transfer req, res, next
pathname = parse(req.url).pathname
filepath = path.join root, pathname

fileTransferer.transfer filepath
else
next()
2 changes: 1 addition & 1 deletion src/file-transfer.coffee
Expand Up @@ -20,7 +20,7 @@ class FileTransferer extends EventEmitter
dataTransferer.on 'complete', (chunk) =>
@.emit 'complete', chunk

transfer: (filepath, callback) ->
transfer: (filepath) ->
fsUtil.readStatsAndFile filepath, (err, payload) =>
if err?
@.emit 'error', err
Expand Down
48 changes: 23 additions & 25 deletions test/connect-file-transfer-spec.coffee
@@ -1,3 +1,5 @@
{EventEmitter} = require 'events'

should = require 'should'
sinon = require 'sinon'

Expand All @@ -12,14 +14,16 @@ describe 'connect-file-transfer', ->
testError = new Error()

it 'should return a function', ->
connect = connectFileTransfer.connect()
fileTransferer = new EventEmitter()
connect = connectFileTransfer.connect fileTransferer
connect.should.be.a 'function'

it 'should use file transferer to transfer the file if it is GET request', ->
testReq =
method: 'GET'
url: testUrl
fileTransferer = transfer: ->
fileTransferer = new EventEmitter()
fileTransferer.transfer = ->
spy = sinon.spy fileTransferer, 'transfer'
connect = connectFileTransfer.connect fileTransferer, testRoot

Expand All @@ -31,7 +35,8 @@ describe 'connect-file-transfer', ->
testReq =
method: 'POST'
url: testUrl
fileTransferer = transfer: ->
fileTransferer = new EventEmitter()
fileTransferer.transfer = ->
spy = sinon.spy fileTransferer, 'transfer'
connect = connectFileTransfer.connect fileTransferer, testRoot

Expand All @@ -41,7 +46,8 @@ describe 'connect-file-transfer', ->

it 'should call next if it is other request', ->
testReq = method: 'otherMethod'
connect = connectFileTransfer.connect()
fileTransferer = new EventEmitter()
connect = connectFileTransfer.connect fileTransferer
nextSpy = sinon.spy()

connect testReq, null, nextSpy
Expand All @@ -53,10 +59,10 @@ describe 'connect-file-transfer', ->
method: 'GET'
url: testUrl

it 'should call back with error and call next', (done) ->
fileTransferer =
transfer: (filepath, callback) ->
callback testError
it 'should call back with error and call next', (done)->
fileTransferer = new EventEmitter()
fileTransferer.transfer = (filepath) ->
@.emit 'error', testError
nextSpy = sinon.spy()

connect = connectFileTransfer.connect fileTransferer, testRoot, (err, data) ->
Expand All @@ -73,11 +79,9 @@ describe 'connect-file-transfer', ->
url: testUrl

it 'should call back with "start" status and response should writehead 200 when file transfer starts to transfer', (done) ->
fileTransferer =
transfer: (filepath, callback) ->
callback null, {
status: 'start'
}
fileTransferer = new EventEmitter()
fileTransferer.transfer = (filepath) ->
@.emit 'start'
testRes = writeHead: ->
writeHeadStub = sinon.stub(testRes, 'writeHead')

Expand All @@ -90,12 +94,9 @@ describe 'connect-file-transfer', ->
connect testReq, testRes

it 'should call response to write content sent by file transferer when it transfers', () ->
fileTransferer =
transfer: (filepath, callback) ->
callback null, {
status: 'transfer'
content: testContent
}
fileTransferer = new EventEmitter()
fileTransferer.transfer = (filepath) ->
@.emit 'transfer', testContent

testRes = write: ->
writeStub = sinon.stub(testRes, 'write')
Expand All @@ -106,12 +107,9 @@ describe 'connect-file-transfer', ->
writeStub.calledWith(testContent).should.be.true

it 'should call response to end with content sent by file transferer and call back with "complete" status when file transferer completes', (done) ->
fileTransferer =
transfer: (filepath, callback) ->
callback null, {
status: 'complete'
content: testContent
}
fileTransferer = new EventEmitter()
fileTransferer.transfer = (filepath) ->
@.emit 'complete', testContent

testRes = end: ->
endStub = sinon.stub(testRes, 'end')
Expand Down

0 comments on commit 70066d9

Please sign in to comment.