Skip to content

Commit

Permalink
Added an example for the gateway : FTP Gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrienCastex committed Jun 19, 2017
1 parent dbbfb12 commit 45f1055
Show file tree
Hide file tree
Showing 9 changed files with 1,140 additions and 0 deletions.
15 changes: 15 additions & 0 deletions examples/gatewayFTP/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Custom FTP gateway

This is an example to show how to use a gateway to manage the content of a remote folder stored on a FTP server.

The folder `ts` and the folder `js` are the same thing. The `js` folder display the example in JavaScript while the `ts` display the example in TypeScript.

## Usage

### Execute

```bash
node index.js
```

But this example needs a fully configured FTP server to connect to.
47 changes: 47 additions & 0 deletions examples/gatewayFTP/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const webdav = require('webdav-server'),
ftpFsManager = require('./js/fsManager.js'),
ftpResource = require('./js/ftpGateway.js');

const ftpConfig = {
host: '127.0.0.1',
port: 21,
connTimeout: 1000,
pasvTimeout: 1000,
user: 'test'
};

const server = new webdav.WebDAVServer({
port: 1900,
autoSave: {
treeFilePath: './data.json',
tempTreeFilePath: './data.tmp.json'
},
autoLoad: {
treeFilePath: './data.json',
fsManagers: [
new webdav.RootFSManager(),
new ftpFsManager.FTPFSManager(ftpConfig),
new webdav.VirtualFSManager()
]
}
});

server.autoLoad((e) => {
if(e)
{
server.addResourceTree(new ftpResource.FTPGateway(ftpConfig, '/', 'ftpGateway'), (e) => {
if(e) throw e;

run();
});
}
else
run();
})

function run()
{
server.start((s) => {
console.log('Server started on port ' + s.address().port + '.');
});
}
67 changes: 67 additions & 0 deletions examples/gatewayFTP/js/fsManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"use strict";
const webdav = require('webdav-server'),
FTPClient = require('ftp'),
ftpResource = require('./Resource'),
ftpGateway = require('./ftpGateway.js');

module.exports.FTPFSManager = function(config)
{
const fsManager = {
config,
uid: 'WebDAVFSManager_1.0.0' + config.host
};
fsManager.constructor = module.exports.FTPFSManager;

fsManager.connect = function(callback)
{
const client = new FTPClient();
client.on('ready', () => callback(client));
client.connect(this.config);
}

fsManager.serialize = function(resource, obj)
{
if(resource.constructor !== ftpGateway.FTPGateway)
return null;

return {
dateCreation: resource.dateCreation,
dateLastModified: resource.dateLastModified,
properties: resource.properties,
name: resource.name,
rootPath: resource.rootPath
};
}

fsManager.unserialize = function(data, obj)
{
const rs = new ftpGateway.FTPGateway(this.config, data.rootPath, data.name, null, this);
rs.dateCreation = data.dateCreation;
rs.dateLastModified = data.dateLastModified;
rs.properties = data.properties;
return rs;
}

fsManager.newResource = function(fullPath, name, type, parent)
{
const parentRemotePath = parent.constructor === ftpGateway.FTPGateway ? parent.rootPath : parent .remotePath;
let remotepath;
if(parentRemotePath.lastIndexOf('/') === parentRemotePath.length - 1)
remotepath = parentRemotePath + name;
else
remotepath = parentRemotePath + '/' + name;

let gateway = parent;
while(gateway && gateway.constructor !== ftpGateway.FTPGateway)
gateway = gateway.parent;

if(type.isFile)
return new ftpResource.FTPFile(gateway, null, remotepath, parent, this);
else if(type.isDirectory)
return new ftpResource.FTPFolder(gateway, null, remotepath, parent, this);

throw webdav.Errors.InvalidOperation;
}

return fsManager;
}
175 changes: 175 additions & 0 deletions examples/gatewayFTP/js/ftpGateway.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
"use strict";
const webdav = require('webdav-server'),
Client = require('ftp'),
ftpResource = require('./Resource'),
ftpFSManager = require('./fsManager.js');

module.exports.FTPGateway = function(config, rootPath, fileName, parent, fsManager)
{
const gateway = new webdav.VirtualFolder(fileName, parent, fsManager ? fsManager : new ftpFSManager.FTPFSManager(config));
gateway.constructor = module.exports.FTPGateway;

gateway.rootPath = rootPath ? rootPath : '/';
gateway.cache = {
'/': gateway
};

gateway.listChildren = function(connection, parent, path, callback)
{
if(path.lastIndexOf('/') !== path.length - 1)
path += '/';

connection.list(path, (e, list) => {
if(e)
{
callback(e);
return;
}

callback(null, list.map((file) => {
const resourcePath = path + file.name;
let resource = this.cache[resourcePath];
if(resource && resource.setInfo)
resource.setInfo(file);
else
{
if(file.type === '-')
resource = new ftpResource.FTPFile(this, file, resourcePath, parent, this.fsManager);
else
resource = new ftpResource.FTPFolder(this, file, resourcePath, parent, this.fsManager);
this.cache[resourcePath] = resource;
}
return resource;
}))
})
}

gateway.find = function(connection, path, callback, forceRefresh = false)
{
const resource = this.cache[path.toString()];
if(forceRefresh || !resource)
{
const parentPath = path.getParent();
this.find(connection, parentPath, (e, parent) => {
if(e)
{
callback(e);
return;
}

parent.getChildren((e, actualChildren) => {
if(e)
{
callback(e);
return;
}

this.listChildren(connection, parent, parentPath.toString(), (e, children) => {
if(e)
{
callback(e);
return;
}

parent.children.children
.filter((c) => c.constructor !== ftpResource.FTPResource && c.constructor !== ftpResource.FTPFile && c.constructor !== ftpResource.FTPFolder)
.forEach((c) => children.push(c));

parent.children.children = children;

new webdav.Workflow()
.each(children, (child, cb) => {
child.webName((e, name) => {
cb(e, !e && name === path.fileName() ? child : null);
})
})
.error(callback)
.done((matchingChildren) => {
for(const child of matchingChildren)
if(child)
{
callback(null, child);
return;
}

callback(webdav.Errors.ResourceNotFound);
})
})
})
})
}
else
callback(null, resource);
}

gateway.refresh = function(requesterPath, callback)
{
const fsPath = new webdav.FSPath(requesterPath);

this.fsManager.connect((c) => {
this.find(c, fsPath, (e) => {
c.end();
callback(e);
}, true)
})
}

gateway.gateway = function(arg, path, callback)
{
const updateChildren = (c, r, cb) =>
{
this.listChildren(c, r, path.toString(), (e, children) => {
if(!e)
{
r.children.children
.filter((c) => c.constructor !== ftpResource.FTPResource && c.constructor !== ftpResource.FTPFile && c.constructor !== ftpResource.FTPFolder)
.forEach((c) => children.push(c));

r.children.children = children;
}

c.end();
cb(e);
})
}

this.fsManager.connect((c) => {
if(path.isRoot())
{
updateChildren(c, this, (e) => {
callback(e, this);
})
return;
}

this.find(c, path, (e, r) => {
if(e)
{
callback(e);
return;
}

r.type((e, type) => {
if(e)
{
callback(e);
return;
}

if(type.isFile)
{
c.end();
callback(e, r);
return;
}

updateChildren(c, r, (e) => {
callback(e, r);
})
})
});
});
}

return gateway;
}
Loading

0 comments on commit 45f1055

Please sign in to comment.