-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added an example for the gateway : FTP Gateway
- Loading branch information
1 parent
dbbfb12
commit 45f1055
Showing
9 changed files
with
1,140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 + '.'); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Oops, something went wrong.