Permalink
Browse files

Add debug mode and some style changes. Fixes #87.

  • Loading branch information...
1 parent a78fb8f commit 0a0d2632743de448b92d21f3f7d3bb904fce577f @sergi committed May 5, 2014
Showing with 107 additions and 22 deletions.
  1. +48 −0 README.md
  2. +42 −22 lib/jsftp.js
  3. +17 −0 test/jsftp_test.js
View
@@ -203,6 +203,54 @@ Refreshes the interval thats keep the server connection active. `wait` is an opt
You can find more usage examples in the [unit tests](https://github.com/sergi/jsftp/blob/master/test/jsftp_test.js). This documentation
will grow as jsftp evolves.
+
+Debugging
+---------
+
+In order to enable debug mode in a FTP connection, a `debugMode` parameter can
+be used in the constructors's config object:
+
+```javascript
+var Ftp = new JSFtp({
+ host: "myserver.com",
+ port: 3331,
+ user: "user",
+ pass: "1234",
+ debugMode: true
+});
+```
+
+It can also be activated or deactivated by calling the `setDebugMode` method:
+
+```javascript
+Ftp.setDebugMode(true); // Debug Mode on
+Ftp.setDebugMode(false; // Debug mode off
+```
+
+If the debug mode is on, the jsftp instance will emit `jsftp_debug` events with
+two parameters: the first is the type of the event and the second and object
+including data related to the event. There are 3 possible types of events:
+
+- `response` events: These are response from the FTP server to the user's FTP
+ commands
+
+- `user_command` events: These are commands that the user issuendss to the
+ FTP server.
+
+- `event:{event name}` events: These are other events mostly related to the server
+ connection, such as `timeout`, `connect` or `disconnect`. For example,
+ a timeout event will have the name `event:timeout`.
+
+In order to react to print all debug events (for example), we would listen to the
+debug messages like this:
+
+```javascript
+Ftp.on('jsftp_debug', function(eventType, data) {
+ console.log('DEBUG: ', eventType);
+ console.log(JSON.stringify(data, null, 2));
+});
+```
+
Installation
------------
View
@@ -17,7 +17,6 @@ var fs = require("fs");
var once = require("once");
var FTP_PORT = 21;
-var DEBUG_MODE = false;
var TIMEOUT = 10 * 60 * 1000;
var IDLE_TIME = 30000;
var NOOP = function() {};
@@ -31,14 +30,17 @@ var COMMANDS = [
"chmod", "size"
];
-function getPasvPort(text) {
+function getPasvPort(text, cb) {
var RE_PASV = /([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/;
var match = RE_PASV.exec(text);
- if (!match) return false;
+ if (!match) {
+ return cb(new Error("Bad passive host/port combination"));
+ }
- // Array containing the passive host and the port number
- return [match[1].replace(/,/g, "."),
- (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255)];
+ cb(null, {
+ host: match[1].replace(/,/g, "."),
+ port: (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255)
+ });
}
function runCmd(cmd) {
@@ -75,21 +77,37 @@ var Ftp = module.exports = function(cfg) {
// Generate generic methods from parameter names. they can easily be
// overriden if we need special behavior. they accept any parameters given,
// it is the responsability of the user to validate the parameters.
- this.raw = function () {
+ this.raw = function() {
return runCmd.apply(this, arguments);
}.bind(this);
COMMANDS.forEach(function(cmd) {
this.raw[cmd] = runCmd.bind(this, cmd);
}, this);
+ var self = this;
+ this.on('data', function(data) {
+ if (self.debugMode) {
+ self.emit('jsftp_debug', 'response', data || {});
+ }
+ });
+
this.socket = this._createSocket(this.port, this.host);
};
util.inherits(Ftp, EventEmitter);
+Ftp.prototype.setDebugMode = function(debugOn) {
+ this.debugMode = (debugOn !== false);
+};
+
Ftp.prototype.reemit = function(event) {
var self = this;
- return function(data) { self.emit(event, data); }
+ return function(data) {
+ self.emit(event, data);
+ if (self.debugMode) {
+ self.emit('jsftp_debug', 'event:' + event, data || {});
+ }
+ }
};
Ftp.prototype._createSocket = function(port, host, firstAction) {
@@ -155,6 +173,10 @@ Ftp.prototype.send = function(command) {
this.emit("cmdSend", command);
this.pipeline.write(command + "\r\n");
+
+ if (this.debugMode) {
+ this.emit('jsftp_debug', 'user_command', command || {});
+ }
};
Ftp.prototype.nextCmd = function() {
@@ -489,11 +511,11 @@ Ftp.prototype.put = function(from, to, callback) {
return callback(new Error("Local file doesn't exist."));
fs.stat(from, function(err, stats) {
- var totalSize = err ? 0 : stats.size;
- var read = fs.createReadStream(from, {
- bufferSize: 4 * 1024
- });
- putReadable(read, to, totalSize, callback);
+ var totalSize = err ? 0 : stats.size;
+ var read = fs.createReadStream(from, {
+ bufferSize: 4 * 1024
+ });
+ putReadable(read, to, totalSize, callback);
});
});
} else {
@@ -546,23 +568,21 @@ Ftp.prototype.pasvTimeout = function(socket, cb) {
socket.destroy();
cb(new Error("Passive socket timeout"));
});
-}
+};
Ftp.prototype.getPasvSocket = function(callback) {
var timeout = this.timeout;
callback = once(callback || NOOP);
this.execute("pasv", function(err, res) {
if (err) return callback(err);
- var pasvRes = getPasvPort(res.text);
- if (pasvRes === false)
- return callback(new Error("PASV: Bad host/port combination"));
+ getPasvPort(res.text, function(err, res) {
+ if (err) return callback(err);
- var host = pasvRes[0];
- var port = pasvRes[1];
- var socket = Net.createConnection(port, host);
- socket.setTimeout(timeout || TIMEOUT);
- callback(null, socket);
+ var socket = Net.createConnection(res.port, res.host);
+ socket.setTimeout(timeout || TIMEOUT);
+ callback(null, socket);
+ });
});
};
View
@@ -743,4 +743,21 @@ describe("jsftp test suite", function() {
next();
}, 5000);
});
+
+ it("Test debug mode", function(next) {
+ var debugCredentials = JSON.parse(JSON.stringify(FTPCredentials));
+ debugCredentials.debugMode = true;
+
+ var ftp2 = new Ftp(debugCredentials);
+ ftp2.once('jsftp_debug', function(type, data) {
+ next();
+ });
+ });
+
+ it("Test debug mode `setDebugMode`", function(next) {
+ ftp.setDebugMode(true);
+ ftp.once('jsftp_debug', function(type, data) {
+ next();
+ });
+ });
});

0 comments on commit 0a0d263

Please sign in to comment.