Compare commits

..

5 Commits

Author SHA1 Message Date
Tyler Stewart
a308a33491 chore: update readme 2018-12-21 16:10:34 -07:00
Tyler Stewart
191ad5507c test: update sinon sandbox creation 2018-12-21 16:07:34 -07:00
Tyler Stewart
281d147b96 chore(package): update scripts 2018-12-21 16:03:13 -07:00
Tyler Stewart
52958ffd9f chore: update packages 2018-12-21 16:00:12 -07:00
Tyler Stewart
3f5d548634 chore(circle): update config 2018-12-21 15:57:04 -07:00
69 changed files with 3142 additions and 3641 deletions

View File

@@ -1,97 +1,103 @@
version: 2
create-cache-file: &create-cache-file
run:
name: Setup cache
command: echo "$NODE_VERSION" > _cache_node_version
package-json-cache: &package-json-cache
key: npm-install-{{ checksum "_cache_node_version" }}-{{ checksum "package-lock.json" }}
base-build: &base-build
steps:
- checkout
- <<: *create-cache-file
- restore_cache:
<<: *package-json-cache
- run:
name: Install
command: npm install
- save_cache:
<<: *package-json-cache
paths:
- node_modules
- run:
name: Lint
command: npm run verify -- --silent
- run:
name: Test
command: npm run test:once
jobs:
build:
test_node_10:
docker:
- image: &node-image circleci/node:lts
steps:
- checkout
- restore_cache:
keys:
- &npm-cache-key npm-cache-{{ .Branch }}-{{ .Revision }}
- npm-cache-{{ .Branch }}
- npm-cache
- run:
name: Install
command: npm ci
- persist_to_workspace:
root: .
paths:
- node_modules
- save_cache:
key: *npm-cache-key
paths:
- ~/.npm/_cacache
- image: circleci/node:10
environment:
- NODE_VERSION: 10
<<: *base-build
lint:
test_node_8:
docker:
- image: *node-image
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Lint
command: npm run verify
- image: circleci/node:8
environment:
- NODE_VERSION: 8
<<: *base-build
test:
test_node_6:
docker:
- image: *node-image
steps:
- checkout
- attach_workspace:
at: .
- deploy:
name: Test
command: |
npm run test
release_dry_run:
docker:
- image: *node-image
steps:
- checkout
- attach_workspace:
at: .
- deploy:
name: Dry Release
command: |
npm run semantic-release -- --dry-run
- image: circleci/node:6
environment:
- NODE_VERSION: 6
<<: *base-build
release:
docker:
- image: *node-image
- image: circleci/node:8
environment:
- NODE_VERSION: 8
steps:
- checkout
- attach_workspace:
at: .
- <<: *create-cache-file
- restore_cache:
<<: *package-json-cache
- deploy:
name: Release
name: Semantic Release
command: |
npm run semantic-release
workflows:
version: 2
publish:
test_and_tag:
jobs:
- build
- lint:
requires:
- build
- test:
requires:
- build
- release_dry_run:
- test_node_10:
filters:
branches:
only: master
- test_node_8:
filters:
branches:
only: master
- test_node_6:
filters:
branches:
only: master
requires:
- test
- lint
- hold_release:
type: approval
requires:
- release_dry_run
- release:
requires:
- hold_release
- test_node_6
- test_node_8
- test_node_10
build_and_test:
jobs:
- test_node_10:
filters:
branches:
ignore: master
- test_node_8:
filters:
branches:
ignore: master
- test_node_6:
filters:
branches:
ignore: master

View File

@@ -1,2 +1,9 @@
# START_CONFIT_GENERATED_CONTENT
# Common folders to ignore
node_modules/*
bower_components/*
# Config folder (optional - you might want to lint this...)
config/*
# END_CONFIT_GENERATED_CONTENT

5
.gitignore vendored
View File

@@ -1,6 +1,7 @@
test_tmp/
node_modules/
dist/
reports/
npm-debug.log
.nyc_output/
test_tmp/

View File

@@ -16,10 +16,5 @@
- Any new fixes are features should include new or updated [tests](/test).
- Commits follow the [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit), please review and commit accordingly
- Submit your pull requests to the `master` branch, these will normally be merged into a separate branch for any finally changes before being merged into `master`.
- Submit any bugs or requests to the issues page in Github.
## Setup
- Clone the repository `git clone`
- Install dependencies `npm install`
- Submit your pull requests to the `master` branch, these will normally be merged into a seperate branch for any finally changes before being merged into `master`.
- Submit any bugs or requests to the issues page in Github.

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Tyler Stewart
Copyright (c) 2018 Tyler Stewart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -36,6 +36,8 @@
## Overview
`ftp-srv` is a modern and extensible FTP server designed to be simple yet configurable.
You can use `ftp-srv` to traverse the file system on the server, but it's biggest strength comes from it's customizable file system. This allows you to serve a custom, dynamic, or unique file system to users. You can even server a different system depending on the user connecting.
## Features
- Extensible [file systems](#file-system) per connection
- Passive and active transfers
@@ -124,9 +126,10 @@ __Allowable values:__
#### `log`
A [bunyan logger](https://github.com/trentm/node-bunyan) instance. Created by default.
#### `timeout`
Sets the timeout (in ms) after that an idle connection is closed by the server
__Default:__ `0`
Piping the output into bunyan will format logs nicely, eg:
```
$ node ./test/start.js | npx bunyan
```
## CLI
@@ -239,16 +242,6 @@ Occurs when a file is uploaded.
`error` if successful, will be `null`
`fileName` name of the file that was uploaded
### `RNTO`
```js
connection.on('RNTO', (error, fileName) => { ... });
```
Occurs when a file is renamed.
`error` if successful, will be `null`
`fileName` name of the file that was renamed
## Supported Commands
See the [command registry](src/commands/registration) for a list of all implemented FTP commands.
@@ -325,34 +318,32 @@ __Used in:__ `SITE CHMOD`
Returns a unique file name to write to
__Used in:__ `STOU`
<!--[RM_CONTRIBUTING]-->
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
<!--[]-->
## Contributors
- [OzairP](https://github.com/OzairP)
- [TimLuq](https://github.com/TimLuq)
- [crabl](https://github.com/crabl)
- [hirviid](https://github.com/hirviid)
- [DiegoRBaquero](https://github.com/DiegoRBaquero)
- [edin-m](https://github.com/edin-m)
- [voxsoftware](https://github.com/voxsoftware)
- [jorinvo](https://github.com/jorinvo)
- [Johnnyrook777](https://github.com/Johnnyrook777)
- [qchar](https://github.com/qchar)
- [mikejestes](https://github.com/mikejestes)
- [jorinvo](https://github.com/jorinvo)
- [voxsoftware](https://github.com/voxsoftware)
- [pkeuter](https://github.com/pkeuter)
- [qiansc](https://github.com/qiansc)
- [broofa](https://github.com/broofa)
- [lafin](https://github.com/lafin)
- [alancnet](https://github.com/alancnet)
- [zgwit](https://github.com/zgwit)
- [TimLuq](https://github.com/TimLuq)
- [edin-mg](https://github.com/edin-m)
- [DiegoRBaquero](https://github.com/DiegoRBaquero)
- [Johnnyrook777](https://github.com/Johnnyrook777)
<!--[RM_LICENSE]-->
## License
This software is licensed under the MIT Licence. See [LICENSE](LICENSE).
<!--[]-->
## References
- [https://cr.yp.to/ftp.html](https://cr.yp.to/ftp.html)

View File

@@ -113,15 +113,11 @@ function setupState(_args) {
}
function startFtpServer(_state) {
// Remove null/undefined options so they get set to defaults, below
for (const key in _state) {
if (_state[key] === undefined) delete _state[key];
}
function checkLogin(data, resolve, reject) {
const user = _state.credentials[data.username];
if (_state.anonymous || user && user.password === data.password) {
return resolve({root: user && user.root || _state.root});
const user = _state.credentials[data.username]
if (_state.anonymous || (user && user.password === data.password)) {
return resolve({root: (user && user.root) || _state.root});
}
return reject(new errors.GeneralError('Invalid username or password', 401));

View File

@@ -0,0 +1,38 @@
'use strict';
module.exports = {
types: [
{value: 'feat', name: 'feat: A new feature'},
{value: 'fix', name: 'fix: A bug fix'},
{value: 'docs', name: 'docs: Documentation only changes'},
{value: 'style', name: 'style: Changes that do not affect the meaning of the code\n (white-space, formatting, missing semi-colons, etc)'},
{value: 'refactor', name: 'refactor: A code change that neither fixes a bug nor adds a feature'},
{value: 'perf', name: 'perf: A code change that improves performance'},
{value: 'test', name: 'test: Adding missing tests'},
{value: 'chore', name: 'chore: Changes to the build process or auxiliary tools\n and libraries such as documentation generation'},
{value: 'revert', name: 'revert: Revert to a commit'},
{value: 'WIP', name: 'WIP: Work in progress'}
],
scopes: [],
// it needs to match the value for field type. Eg.: 'fix'
/*
scopeOverrides: {
fix: [
{name: 'merge'},
{name: 'style'},
{name: 'e2eTest'},
{name: 'unitTest'}
]
},
*/
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix'],
// Appends the branch name to the footer of the commit. Useful for tracking commits after branches have been merged
appendBranchNameToCommitMessage: false
};

View File

@@ -0,0 +1,5 @@
test/**/*.spec.js
--reporter mocha-multi-reporters
--reporter-options configFile=config/testUnit/reporters.json
--ui bdd
--bail

View File

@@ -0,0 +1,6 @@
{
"reporterEnabled": "spec",
"mochaJunitReporterReporterOptions": {
"mochaFile": "reports/junit.xml"
}
}

162
config/verify/.eslintrc Normal file
View File

@@ -0,0 +1,162 @@
{
"extends": "eslint:recommended",
"env": {
"node": true,
"mocha": true,
"es6": true
},
"plugins": [
"mocha",
"node"
],
"rules": {
"mocha/no-exclusive-tests": 2,
"no-warning-comments": [
1,
{
"terms": ["todo", "fixme", "xxx"],
"location": "start"
},
],
"object-curly-spacing": [
2,
"never"
],
"array-bracket-spacing": [
2,
"never"
],
"brace-style": [
2,
"1tbs"
],
"consistent-return": 0,
"indent": [
"error",
2,
{
"SwitchCase": 1,
"MemberExpression": "off"
}
],
"no-multiple-empty-lines": [
2,
{
"max": 2
}
],
"no-use-before-define": [
2,
"nofunc"
],
"one-var": [
2,
"never"
],
"quote-props": [
2,
"as-needed"
],
"quotes": [
2,
"single"
],
"keyword-spacing": 2,
"space-before-function-paren": [
2,
{
"anonymous": "always",
"named": "never"
}
],
"space-in-parens": [
2,
"never"
],
"strict": [
2,
"global"
],
"curly": [
2,
"multi-line"
],
"eol-last": 2,
"key-spacing": [
2,
{
"beforeColon": false,
"afterColon": true
}
],
"no-eval": 2,
"no-with": 2,
"space-infix-ops": 2,
"dot-notation": [
2,
{
"allowKeywords": true
}
],
"eqeqeq": 2,
"no-alert": 2,
"no-caller": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-implied-eval": 2,
"no-iterator": 2,
"no-label-var": 2,
"no-labels": 2,
"no-lone-blocks": 2,
"no-loop-func": 2,
"no-multi-spaces": 2,
"no-multi-str": 2,
"no-native-reassign": 2,
"no-new": 2,
"no-new-func": 2,
"no-new-wrappers": 2,
"no-octal-escape": 2,
"no-proto": 2,
"no-return-assign": 2,
"no-script-url": 2,
"no-sequences": 2,
"no-unused-expressions": 2,
"yoda": 2,
"no-shadow": 2,
"no-shadow-restricted-names": 2,
"no-undef-init": 2,
"no-console": 1,
"camelcase": [
0,
{
"properties": "never"
}
],
"comma-spacing": 2,
"comma-dangle": 1,
"new-cap": 2,
"new-parens": 2,
"arrow-parens": [2, "always"],
"no-array-constructor": 2,
"array-callback-return": 1,
"no-extra-parens": 2,
"no-new-object": 2,
"no-spaced-func": 2,
"no-trailing-spaces": 2,
"no-underscore-dangle": 0,
"no-fallthrough": 0,
"semi": 2,
"semi-spacing": [
2,
{
"before": false,
"after": true
}
]
},
"parserOptions": {
"emcaVersion": 6,
"sourceType": "module",
"impliedStrict": true
}
}

5
ftp-srv.d.ts vendored
View File

@@ -64,13 +64,12 @@ export interface FtpServerOptions {
pasv_max?: number,
pasv_url?: string,
greeting?: string | string[],
tls?: tls.SecureContextOptions | false,
tls?: tls.SecureContext | false,
anonymous?: boolean,
blacklist?: Array<string>,
whitelist?: Array<string>,
file_format?: (stat: Stats) => string | Promise<string> | "ls" | "ep",
log?: any,
timeout?: number
log?: any,
}
export class FtpServer extends EventEmitter {

View File

@@ -1,27 +0,0 @@
const {get} = require('https');
get('https://api.github.com/repos/trs/ftp-srv/contributors', {
headers: {
'User-Agent': 'Chrome'
}
}, (res) => {
let response = '';
res.on('data', (data) => {
response += data;
});
res.on('end', () => {
const contributors = JSON.parse(response)
.filter((contributor) => contributor.type === 'User');
for (const contributor of contributors) {
const url = contributor.html_url;
const username = contributor.login;
const markdown = `- [${username}](${url})\n`;
process.stdout.write(markdown);
}
});
}).on('error', (err) => {
process.stderr.write(err);
});

5868
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ftp-srv",
"version": "0.0.0",
"version": "0.0.0-development",
"description": "Modern, extensible FTP Server",
"keywords": [
"ftp",
@@ -26,40 +26,24 @@
},
"scripts": {
"pre-release": "npm run verify",
"commitmsg": "cz-customizable-ghooks",
"dev": "cross-env NODE_ENV=development npm run verify:watch",
"prepush": "npm run verify && npm run test:once --silent",
"semantic-release": "semantic-release",
"test": "mocha **/*.spec.js --ui bdd --bail",
"verify": "eslint src/**/*.js test/**/*.js bin/**/*.js"
"start": "npm run dev",
"test": "cross-env NODE_ENV=test mocha --opts config/testUnit/mocha.opts -w",
"test:once": "cross-env NODE_ENV=test mocha --opts config/testUnit/mocha.opts",
"verify": "eslint -c config/verify/.eslintrc \"src/**/*.js\" \"test/**/*.js\""
},
"release": {
"verifyConditions": "condition-circle"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"eslintConfig": {
"extends": "eslint:recommended",
"env": {
"node": true,
"mocha": true,
"es6": true
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
"cz-customizable": {
"config": "config/release/commitMessageConfig.js"
}
},
"dependencies": {
@@ -67,25 +51,33 @@
"bunyan": "^1.8.12",
"ip": "^1.1.5",
"lodash": "^4.17.10",
"moment": "^2.22.1",
"uuid": "^3.2.1",
"yargs": "^11.0.0"
"moment": "^2.22.2",
"uuid": "^3.3.2",
"yargs": "^12.0.1"
},
"devDependencies": {
"@commitlint/cli": "^7.5.2",
"@commitlint/config-conventional": "^7.5.0",
"@icetee/ftp": "^1.0.2",
"chai": "^4.2.0",
"condition-circle": "^2.0.2",
"eslint": "^5.14.1",
"husky": "^1.3.1",
"lint-staged": "^8.1.4",
"@icetee/ftp": "^1.0.3",
"chai": "^4.1.2",
"condition-circle": "^2.0.1",
"cross-env": "5.2.0",
"cz-customizable": "5.2.0",
"cz-customizable-ghooks": "1.5.0",
"eslint": "5.3.0",
"eslint-config-google": "0.9.1",
"eslint-friendly-formatter": "4.0.1",
"eslint-plugin-mocha": "^5.1.0",
"eslint-plugin-node": "7.0.1",
"husky": "0.14.3",
"istanbul": "0.4.5",
"mocha": "^5.2.0",
"rimraf": "^2.6.1",
"semantic-release": "^15.10.6",
"sinon": "^2.3.5"
"mocha-junit-reporter": "1.18.0",
"mocha-multi-reporters": "1.1.7",
"rimraf": "2.6.2",
"semantic-release": "^15.9.8",
"sinon": "^6.1.5"
},
"engines": {
"node": ">=6.x"
"node": ">=6.x",
"npm": ">=5.x"
}
}

View File

@@ -2,11 +2,7 @@ const PassiveConnector = require('../../connector/passive');
module.exports = {
directive: 'PASV',
handler: function ({log} = {}) {
if (!this.server.options.pasv_url) {
return this.reply(502);
}
handler: function () {
this.connector = new PassiveConnector(this);
return this.connector.setupServer()
.then((server) => {
@@ -17,10 +13,6 @@ module.exports = {
const portByte2 = port % 256;
return this.reply(227, `PASV OK (${host},${portByte1},${portByte2})`);
})
.catch((err) => {
log.error(err);
return this.reply(425);
});
},
syntax: '{{cmd}}',

View File

@@ -3,7 +3,7 @@ const ActiveConnector = require('../../connector/active');
module.exports = {
directive: 'PORT',
handler: function ({log, command} = {}) {
handler: function ({command} = {}) {
this.connector = new ActiveConnector(this);
const rawConnection = _.get(command, 'arg', '').split(',');
@@ -14,11 +14,7 @@ module.exports = {
const port = portBytes[0] * 256 + portBytes[1];
return this.connector.setupConnection(ip, port)
.then(() => this.reply(200))
.catch((err) => {
log.error(err);
return this.reply(425);
});
.then(() => this.reply(200));
},
syntax: '{{cmd}} <x>,<x>,<x>,<x>,<y>,<y>',
description: 'Specifies an address and port to which the server should connect'

View File

@@ -15,10 +15,8 @@ module.exports = {
.then(() => {
return this.reply(250);
})
.tap(() => this.emit('RNTO', null, to))
.catch((err) => {
log.error(err);
this.emit('RNTO', err);
return this.reply(550, err.message);
})
.finally(() => {

View File

@@ -22,7 +22,7 @@ module.exports = {
const destroyConnection = (connection, reject) => (err) => {
if (connection) {
if (connection.writable) connection.end();
if (connection.writeable) connection.end();
connection.destroy(err);
}
reject(err);
@@ -36,7 +36,7 @@ module.exports = {
const socketPromise = new Promise((resolve, reject) => {
this.connector.socket.on('data', (data) => {
if (this.connector.socket) this.connector.socket.pause();
if (stream && stream.writable) {
if (stream) {
stream.write(data, this.transferType, () => this.connector.socket && this.connector.socket.resume());
}
});

View File

@@ -30,10 +30,7 @@ class FtpConnection extends EventEmitter {
this.server.emit('client-error', {connection: this, context: 'commandSocket', error: err});
});
this.commandSocket.on('data', this._handleData.bind(this));
this.commandSocket.on('timeout', () => {
this.log.trace('Client timeout');
this.close().catch((e) => this.log.trace(e, 'Client close error'));
});
this.commandSocket.on('timeout', () => {});
this.commandSocket.on('close', () => {
if (this.connector) this.connector.end();
if (this.commandSocket && !this.commandSocket.destroyed) this.commandSocket.destroy();

View File

@@ -1,56 +1,33 @@
const net = require('net');
const Promise = require('bluebird');
const errors = require('../errors');
const MAX_PORT = 65535;
const MAX_PORT_CHECK_ATTEMPT = 5;
function* portNumberGenerator(min, max = MAX_PORT) {
function* portNumberGenerator(min, max) {
let current = min;
while (true) {
if (current > MAX_PORT || current > max) {
if (current > 65535 || current > max) {
current = min;
}
yield current++;
}
}
function getNextPortFactory(host, portMin, portMax, maxAttempts = MAX_PORT_CHECK_ATTEMPT) {
const nextPortNumber = portNumberGenerator(portMin, portMax);
function getNextPortFactory(min, max = Infinity) {
const nextPortNumber = portNumberGenerator(min, max);
const portCheckServer = net.createServer();
portCheckServer.maxConnections = 0;
return () => new Promise((resolve, reject) => {
let attemptCount = 0;
const tryGetPort = () => {
attemptCount++;
if (attemptCount > maxAttempts) {
reject(new errors.ConnectorError('Unable to find valid port'));
return;
}
const {value: port} = nextPortNumber.next();
portCheckServer.removeAllListeners();
portCheckServer.once('error', (err) => {
if (['EADDRINUSE'].includes(err.code)) {
tryGetPort();
} else {
reject(err);
}
});
portCheckServer.once('listening', () => {
portCheckServer.close(() => resolve(port));
});
try {
portCheckServer.listen(port, host);
} catch (err) {
reject(err);
}
};
tryGetPort();
portCheckServer.on('error', () => {
portCheckServer.listen(nextPortNumber.next().value);
});
return () => new Promise((resolve) => {
portCheckServer.once('listening', () => {
const {port} = portCheckServer.address();
portCheckServer.close(() => resolve(port));
});
portCheckServer.listen(nextPortNumber.next().value);
})
.catch(RangeError, (err) => Promise.reject(new errors.ConnectorError(err.message)));
}
module.exports = {

View File

@@ -0,0 +1,25 @@
const http = require('http');
const Promise = require('bluebird');
const errors = require('../errors');
const IP_WEBSITE = 'http://api.ipify.org/';
module.exports = function (hostname) {
return new Promise((resolve, reject) => {
if (!hostname || hostname === '0.0.0.0') {
let ip = '';
http.get(IP_WEBSITE, (response) => {
if (response.statusCode !== 200) {
return reject(new errors.GeneralError('Unable to resolve hostname', response.statusCode));
}
response.setEncoding('utf8');
response.on('data', (chunk) => {
ip += chunk;
});
response.on('end', () => {
resolve(ip);
});
});
} else resolve(hostname);
});
};

View File

@@ -7,6 +7,7 @@ const tls = require('tls');
const EventEmitter = require('events');
const Connection = require('./connection');
const resolveHost = require('./helpers/resolve-host');
const {getNextPortFactory} = require('./helpers/find-port');
class FtpServer extends EventEmitter {
@@ -23,8 +24,7 @@ class FtpServer extends EventEmitter {
blacklist: [],
whitelist: [],
greeting: null,
tls: false,
timeout: 0
tls: false
}, options);
this._greeting = this.setupGreeting(this.options.greeting);
@@ -36,15 +36,10 @@ class FtpServer extends EventEmitter {
this.log = this.options.log;
this.url = nodeUrl.parse(this.options.url);
this.getNextPasvPort = getNextPortFactory(
_.get(this, 'url.hostname'),
_.get(this, 'options.pasv_min'),
_.get(this, 'options.pasv_max'));
const timeout = Number(this.options.timeout);
this.options.timeout = isNaN(timeout) ? 0 : Number(timeout);
const serverConnectionHandler = (socket) => {
socket.setTimeout(this.options.timeout);
let connection = new Connection(this, {log: this.log, socket});
this.connections[connection.id] = connection;
@@ -72,21 +67,22 @@ class FtpServer extends EventEmitter {
}
listen() {
if (!this.options.pasv_url) {
this.log.warn('Passive URL not set. Passive connections not available.');
}
return resolveHost(this.options.pasv_url || this.url.hostname)
.then((pasvUrl) => {
this.options.pasv_url = pasvUrl;
return new Promise((resolve, reject) => {
this.server.once('error', reject);
this.server.listen(this.url.port, this.url.hostname, (err) => {
this.server.removeListener('error', reject);
if (err) return reject(err);
this.log.info({
protocol: this.url.protocol.replace(/\W/g, ''),
ip: this.url.hostname,
port: this.url.port
}, 'Listening');
resolve('Listening');
return new Promise((resolve, reject) => {
this.server.once('error', reject);
this.server.listen(this.url.port, this.url.hostname, (err) => {
this.server.removeListener('error', reject);
if (err) return reject(err);
this.log.info({
protocol: this.url.protocol.replace(/\W/g, ''),
ip: this.url.hostname,
port: this.url.port
}, 'Listening');
resolve('Listening');
});
});
});
}

View File

@@ -20,7 +20,7 @@ describe('FtpCommands', function () {
};
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
commands = new FtpCommands(mockConnection);

View File

@@ -15,7 +15,7 @@ describe.skip(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
sandbox.spy(mockClient.connector, 'waitForConnection');

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -16,7 +16,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -16,7 +16,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
sandbox.spy(mockClient.fs, 'chdir');

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'chdir').resolves();

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'delete').resolves();

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
sandbox.stub(ActiveConnector.prototype, 'setupConnection').resolves();

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(PassiveConnector.prototype, 'setupServer').resolves({

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -25,7 +25,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'get').resolves({

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'get').resolves({mtime: 'Mon, 10 Oct 2011 23:24:11 GMT'});

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'mkdir').resolves();

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -25,7 +25,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'get').resolves({

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -15,7 +15,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient, 'login').resolves();

View File

@@ -12,7 +12,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
sandbox.stub(ActiveConnector.prototype, 'setupConnection').resolves();

View File

@@ -12,7 +12,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
sandbox.stub(mockClient.fs, 'currentDirectory').resolves();

View File

@@ -10,7 +10,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'close').resolves();
});

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -25,7 +25,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.fs = {
read: () => {}

View File

@@ -10,7 +10,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.renameFrom = 'test';
mockClient.fs = {

View File

@@ -1,18 +1,16 @@
const Promise = require('bluebird');
const {expect} = require('chai');
const sinon = require('sinon');
const EventEmitter = require('events');
const CMD = 'RNTO';
describe(CMD, function () {
let sandbox;
const mockLog = {error: () => {}};
let emitter;
const mockClient = {reply: () => Promise.resolve()};
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.renameFrom = 'test';
mockClient.fs = {
@@ -20,9 +18,6 @@ describe(CMD, function () {
rename: () => Promise.resolve()
};
emitter = new EventEmitter();
mockClient.emit = emitter.emit.bind(emitter);
sandbox.spy(mockClient, 'reply');
sandbox.spy(mockClient.fs, 'rename');
});

View File

@@ -10,7 +10,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../../src/commands/registration/site/${CMD.toLowerCase()}`).bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.fs = {
chmod: () => Promise.resolve()

View File

@@ -17,7 +17,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.stub(mockClient, 'reply').resolves();
});

View File

@@ -10,7 +10,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.fs = {
get: () => Promise.resolve({size: 1})

View File

@@ -10,7 +10,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.fs = {
get: () => Promise.resolve({}),

View File

@@ -25,7 +25,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.fs = {
write: () => {}

View File

@@ -13,7 +13,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.fs = {
get: () => Promise.resolve(),

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
sandbox.spy(mockClient, 'reply');
});

View File

@@ -11,7 +11,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
mockClient.transferType = null;
sandbox.spy(mockClient, 'reply');

View File

@@ -16,7 +16,7 @@ describe(CMD, function () {
const cmdFn = require(`../../../src/commands/registration/${CMD.toLowerCase()}`).handler.bind(mockClient);
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
delete mockClient.username;
mockClient.server.options = {};

View File

@@ -9,8 +9,7 @@ const ActiveConnector = require('../../src/connector/active');
const {getNextPortFactory} = require('../../src/helpers/find-port');
describe('Connector - Active //', function () {
const host = '127.0.0.1';
let getNextPort = getNextPortFactory(host, 1024);
let getNextPort = getNextPortFactory(1024);
let PORT;
let active;
let mockConnection = {};
@@ -21,7 +20,7 @@ describe('Connector - Active //', function () {
active = new ActiveConnector(mockConnection);
});
beforeEach((done) => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
getNextPort()
.then((port) => {
@@ -37,7 +36,7 @@ describe('Connector - Active //', function () {
});
it('sets up a connection', function () {
return active.setupConnection(host, PORT)
return active.setupConnection('127.0.0.1', PORT)
.then(() => {
expect(active.dataSocket).to.exist;
});
@@ -46,7 +45,7 @@ describe('Connector - Active //', function () {
it('destroys existing connection, then sets up a connection', function () {
const destroyFnSpy = sandbox.spy(active.dataSocket, 'destroy');
return active.setupConnection(host, PORT)
return active.setupConnection('127.0.0.1', PORT)
.then(() => {
expect(destroyFnSpy.callCount).to.equal(1);
expect(active.dataSocket).to.exist;
@@ -54,7 +53,7 @@ describe('Connector - Active //', function () {
});
it('waits for connection', function () {
return active.setupConnection(host, PORT)
return active.setupConnection('127.0.0.1', PORT)
.then(() => {
expect(active.dataSocket).to.exist;
return active.waitForConnection();
@@ -74,7 +73,7 @@ describe('Connector - Active //', function () {
}
};
return active.setupConnection(host, PORT)
return active.setupConnection('127.0.0.1', PORT)
.then(() => {
expect(active.dataSocket).to.exist;
return active.waitForConnection();

View File

@@ -10,7 +10,6 @@ const PassiveConnector = require('../../src/connector/passive');
const {getNextPortFactory} = require('../../src/helpers/find-port');
describe('Connector - Passive //', function () {
const host = '127.0.0.1';
let mockConnection = {
reply: () => Promise.resolve({}),
close: () => Promise.resolve({}),
@@ -21,7 +20,7 @@ describe('Connector - Passive //', function () {
},
server: {
url: '',
getNextPasvPort: getNextPortFactory(host, 1024)
getNextPasvPort: getNextPortFactory(1024)
}
};
let sandbox;
@@ -49,7 +48,7 @@ describe('Connector - Passive //', function () {
describe('setup', function () {
before(function () {
sandbox.stub(mockConnection.server, 'getNextPasvPort').value(getNextPortFactory(host));
sandbox.stub(mockConnection.server, 'getNextPasvPort').value(getNextPortFactory());
});
it('no pasv range provided', function (done) {
@@ -57,7 +56,7 @@ describe('Connector - Passive //', function () {
passive.setupServer()
.catch((err) => {
try {
expect(err.name).to.contain('RangeError');
expect(err.name).to.equal('ConnectorError');
done();
} catch (ex) {
done(ex);
@@ -69,7 +68,7 @@ describe('Connector - Passive //', function () {
describe('setup', function () {
let connection;
before(function () {
sandbox.stub(mockConnection.server, 'getNextPasvPort').value(getNextPortFactory(host, -1, -1));
sandbox.stub(mockConnection.server, 'getNextPasvPort').value(getNextPortFactory(-1, -1));
connection = new PassiveConnector(mockConnection);
});
@@ -77,7 +76,7 @@ describe('Connector - Passive //', function () {
it('has invalid pasv range', function (done) {
connection.setupServer()
.catch((err) => {
expect(err.name).to.contain('RangeError');
expect(err.name).to.equal('ConnectorError');
done();
});
});

View File

@@ -9,7 +9,7 @@ describe('helpers // file-stat', function () {
let sandbox;
before(function () {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
});
afterEach(function () {
sandbox.restore();

View File

@@ -1,29 +1,52 @@
/* eslint no-unused-expressions: 0 */
const {expect} = require('chai');
const net = require('net');
const sinon = require('sinon');
const {getNextPortFactory} = require('../../src/helpers/find-port');
describe('helpers // find-port', function () {
describe('keeps trying new ports', () => {
let getNextPort;
let serverAlreadyRunning;
beforeEach((done) => {
getNextPort = getNextPortFactory('::', 8821);
let sandbox;
let getNextPort;
serverAlreadyRunning = net.createServer();
serverAlreadyRunning.listen(8821, () => done());
beforeEach(() => {
sandbox = sinon.createSandbox().usingPromise(Promise);
getNextPort = getNextPortFactory(1, 2);
});
afterEach(() => {
sandbox.restore();
});
it('finds a port', () => {
sandbox.stub(net.Server.prototype, 'listen').callsFake(function (port) {
this.address = () => ({port});
setImmediate(() => this.emit('listening'));
});
afterEach((done) => {
serverAlreadyRunning.close(() => done());
return getNextPort()
.then((port) => {
expect(port).to.equal(1);
});
});
it('restarts count', () => {
sandbox.stub(net.Server.prototype, 'listen').callsFake(function (port) {
this.address = () => ({port});
setImmediate(() => this.emit('listening'));
});
it('test', () => {
return getNextPort()
.then((port) => {
expect(port).to.equal(8822);
});
return getNextPort()
.then((port) => {
expect(port).to.equal(1);
})
.then(() => getNextPort())
.then((port) => {
expect(port).to.equal(2);
})
.then(() => getNextPort())
.then((port) => {
expect(port).to.equal(1);
});
});
});

View File

@@ -0,0 +1,51 @@
const {expect} = require('chai');
const sinon = require('sinon');
const resolveHost = require('../../src/helpers/resolve-host');
describe('helpers //resolve-host', function () {
this.timeout(4000);
let sandbox;
beforeEach(() => {
sandbox = sinon.createSandbox().usingPromise(Promise);
});
afterEach(() => sandbox.restore());
it('fetches ip address', () => {
const hostname = '0.0.0.0';
return resolveHost(hostname)
.then((resolvedHostname) => {
expect(resolvedHostname).to.match(/^\d+\.\d+\.\d+\.\d+$/);
});
});
it('fetches ip address', () => {
const hostname = null;
return resolveHost(hostname)
.then((resolvedHostname) => {
expect(resolvedHostname).to.match(/^\d+\.\d+\.\d+\.\d+$/);
});
});
it('does nothing', () => {
const hostname = '127.0.0.1';
return resolveHost(hostname)
.then((resolvedHostname) => {
expect(resolvedHostname).to.equal(hostname);
});
});
it('fails on getting hostname', () => {
sandbox.stub(require('http'), 'get').callsFake(function (url, cb) {
cb({
statusCode: 420
});
});
return resolveHost(null)
.then(() => expect(1).to.equal(2))
.catch((err) => {
expect(err.code).to.equal(420);
});
});
});

View File

@@ -25,7 +25,7 @@ describe('Integration', function () {
return startServer({url: 'ftp://127.0.0.1:8880'});
});
beforeEach(() => {
sandbox = sinon.sandbox.create().usingPromise(Promise);
sandbox = sinon.createSandbox().usingPromise(Promise);
});
afterEach(() => sandbox.restore());
after(() => server.close());
@@ -48,7 +48,6 @@ describe('Integration', function () {
function startServer(options = {}) {
server = new FtpServer(_.assign({
log,
pasv_url: '127.0.0.1',
pasv_min: 8881,
greeting: ['hello', 'world'],
anonymous: true
@@ -179,7 +178,7 @@ describe('Integration', function () {
const fsPath = `${clientDirectory}/${name}/fail.txt`;
sandbox.stub(connection.fs, 'write').callsFake(function () {
const stream = fs.createWriteStream(fsPath, {flags: 'w+', autoClose: false});
const stream = fs.createWriteStream(fsPath, {flags: 'w+'});
stream.on('error', () => fs.existsSync(fsPath) && fs.unlinkSync(fsPath));
stream.on('close', () => stream.end());
setImmediate(() => stream.emit('error', new Error('STOR fail test')));
@@ -404,7 +403,7 @@ describe('Integration', function () {
readFile(`${process.cwd()}/test/cert/server.csr`)
]))
.then(([key, cert, ca]) => startServer({
url: 'ftp://127.0.0.1:8881',
url: 'ftp://127.0.0.1:8880',
tls: {key, cert, ca}
}))
.then(() => {
@@ -432,7 +431,7 @@ describe('Integration', function () {
readFile(`${process.cwd()}/test/cert/server.csr`)
]))
.then(([key, cert, ca]) => startServer({
url: 'ftps://127.0.0.1:8882',
url: 'ftps://127.0.0.1:8880',
tls: {key, cert, ca}
}))
.then(() => {

View File

@@ -5,7 +5,6 @@ const FtpServer = require('../src');
const server = new FtpServer({
log: bunyan.createLogger({name: 'test', level: 'trace'}),
url: 'ftp://127.0.0.1:8880',
pasv_url: '127.0.0.1',
pasv_min: 8881,
greeting: ['Welcome', 'to', 'the', 'jungle!'],
tls: {