Skip to content

Commit

Permalink
Check port availability before starting server
Browse files Browse the repository at this point in the history
  • Loading branch information
tommy351 committed Jan 31, 2015
1 parent 4112d30 commit ffa7a87
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 37 deletions.
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"trailing": true,
"quotmark": "single",
"undef": true,
"strict": true,
"unused": "vars",
"globals": {
"Promise": true
Expand Down
6 changes: 4 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
var merge = require('utils-merge');
'use strict';

hexo.config.server = merge({
var assign = require('object-assign');

hexo.config.server = assign({
port: 4000,
log: false,
ip: '0.0.0.0'
Expand Down
2 changes: 2 additions & 0 deletions lib/middlewares/gzip.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var compress = require('compression');

module.exports = function(app){
Expand Down
2 changes: 2 additions & 0 deletions lib/middlewares/header.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

module.exports = function(app){
app.use(function(req, res, next){
res.setHeader('X-Powered-By', 'Hexo');
Expand Down
2 changes: 2 additions & 0 deletions lib/middlewares/logger.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var morgan = require('morgan');

module.exports = function(app){
Expand Down
2 changes: 2 additions & 0 deletions lib/middlewares/redirect.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

module.exports = function(app){
var root = this.config.root;
if (root === '/') return;
Expand Down
2 changes: 2 additions & 0 deletions lib/middlewares/route.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var pathFn = require('path');
var mime = require('mime');

Expand Down
2 changes: 2 additions & 0 deletions lib/middlewares/static.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var serveStatic = require('serve-static');

module.exports = function(app){
Expand Down
43 changes: 29 additions & 14 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
'use strict';

var connect = require('connect');
var http = require('http');
var chalk = require('chalk');
var Promise = require('bluebird');
var format = require('util').format;
var open = require('open');
var net = require('net');

function server(args){
module.exports = function(args){
var app = connect();
var config = this.config;
var ip = args.i || args.ip || config.server.ip || 'localhost';
var port = parseInt(args.p || args.port || config.server.port, 10) || 4000;
var root = config.root;
var self = this;

if (port > 65535 || port < 1){
throw new Error('Port number ' + port + ' is invalid. Try a number between 1 and 65535.');
}

return this.extend.filter.exec('server_middleware', app, {context: this}).then(function(){
if (args.$test_mode){
return self.load();
} else {
return self.watch();
}
return checkPort(ip, port).then(function(){
return self.extend.filter.exec('server_middleware', app, {context: self});
}).then(function(){
return self.watch();
}).then(function(){
return startServer(http.createServer(app), port, ip);
}).then(function(server){
Expand All @@ -35,7 +32,7 @@ function server(args){
}

return server;
}, function(err){
}).catch(function(err){
switch (err.code){
case 'EADDRINUSE':
self.log.fatal('Port %d has been used. Try other port instead.', port);
Expand All @@ -46,9 +43,10 @@ function server(args){
break;
}

self.unwatch();
throw err;
});
}
};

function startServer(server, port, ip){
return new Promise(function(resolve, reject){
Expand All @@ -60,4 +58,21 @@ function startServer(server, port, ip){
});
}

module.exports = server;
function checkPort(ip, port){
return new Promise(function(resolve, reject){
if (port > 65535 || port < 1){
return reject(new Error('Port number ' + port + ' is invalid. Try a number between 1 and 65535.'));
}

var server = net.createServer();

server.once('error', reject);

server.once('listening', function(){
server.close();
resolve();
});

server.listen(port, ip);
});
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"connect": "3.x",
"mime": "^1.2.11",
"morgan": "^1.5.0",
"object-assign": "^2.0.0",
"open": "0.0.5",
"serve-static": "^1.7.1",
"utils-merge": "^1.0.0"
"serve-static": "^1.7.1"
},
"devDependencies": {
"chai": "^1.9.1",
Expand All @@ -40,7 +40,7 @@
"gulp-jshint": "^1.8.6",
"gulp-load-plugins": "^0.8.0",
"gulp-mocha": "^2.0.0",
"hexo": "^3.0.0-beta.2",
"hexo": "^3.0.0-rc.2",
"hexo-fs": "0.0.8",
"jshint-stylish": "^1.0.0",
"mocha": "^2.0.1",
Expand Down
15 changes: 15 additions & 0 deletions test/.jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"eqnull": true,
"expr": true,
"indent": 2,
"node": true,
"mocha": true,
"trailing": true,
"quotmark": "single",
"undef": true,
"strict": true,
"unused": "vars",
"globals": {
"Promise": true
}
}
71 changes: 53 additions & 18 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
'use strict';

var should = require('chai').should();
var Hexo = require('hexo');
var request = require('supertest');
var pathFn = require('path');
var fs = require('hexo-fs');
var Promise = require('bluebird');
var net = require('net');

describe('server', function(){
var hexo = new Hexo(pathFn.join(__dirname, 'server_test'), {silent: true});
Expand Down Expand Up @@ -43,27 +46,35 @@ describe('server', function(){
});
});

afterEach(function(){
return hexo.unwatch();
});

after(function(){
return fs.rmdir(hexo.base_dir);
});

function stopServer(app, callback){
return function(err){
if (err) return callback(err);
app.close(callback);
app.close(function(err_){
if (err) return callback(err);
if (err_) return callback(err_);

callback();
});
};
}

it('X-Powered-By header', function(done){
server({$test_mode: true}).then(function(app){
server({}).then(function(app){
request('http://localhost:4000').get('/')
.expect('X-Powered-By', 'Hexo')
.expect(200, 'index', stopServer(app, done));
});
});

it('Content-Type header', function(done){
server({$test_mode: true}).then(function(app){
server({}).then(function(app){
request('http://localhost:4000').get('/bar.jpg')
.expect('Content-Type', 'image/jpeg')
.end(stopServer(app, done));
Expand All @@ -72,7 +83,7 @@ describe('server', function(){

it('static asset', function(done){
fs.writeFile(pathFn.join(hexo.public_dir, 'test.html'), 'test html').then(function(){
server({$test_mode: true}).then(function(app){
server({}).then(function(app){
request('http://localhost:4000').get('/test.html')
.expect('Content-Type', 'text/html; charset=UTF-8')
.expect(200, 'test html', stopServer(app, done));
Expand All @@ -81,36 +92,60 @@ describe('server', function(){
});

it('invalid port', function(){
try {
server({port: -100});
} catch (err){
return server({port: -100}).catch(function(err){
err.should.have.property('message', 'Port number -100 is invalid. Try a number between 1 and 65535.');
}
});
});

it('invalid port > 65535', function(){
return server({port: 65536}).catch(function(err){
err.should.have.property('message', 'Port number 65536 is invalid. Try a number between 1 and 65535.');
});
});

try {
server({port: 70000});
} catch (err){
err.should.have.property('message', 'Port number 70000 is invalid. Try a number between 1 and 65535.');
}
it('change port setting', function(done){
server({port: 5000}).then(function(app){
request('http://localhost:5000').get('/')
.expect(200, 'index', stopServer(app, done));
});
});

it('check port before starting', function(callback){
var s = net.createServer();

s.listen(4000, function(){
server({}).catch(function(err){
err.code.should.eql('EADDRINUSE');
callback();
}).finally(function(){
s.close();
});
});
});

it('change ip setting', function(){
return server({ip: '1.2.3.4'}).catch(function(err){
err.code.should.eql('EADDRNOTAVAIL');
});
});

it('append trailing slash', function(done){
server({$test_mode: true}).then(function(app){
server({}).then(function(app){
request('http://localhost:4000').get('/foo')
.expect('Location', '/foo/')
.expect(302, 'Redirecting', stopServer(app, done));
});
});

it('don\'t append trailing slash if URL has a extension name', function(done){
server({$test_mode: true}).then(function(app){
server({}).then(function(app){
request('http://localhost:4000').get('/bar.txt')
.expect(404, stopServer(app, done));
});
});

it('only send headers on HEAD request', function(done){
server({$test_mode: true}).then(function(app){
server({}).then(function(app){
request('http://localhost:4000').head('/')
.expect(200, '', stopServer(app, done));
});
Expand All @@ -119,7 +154,7 @@ describe('server', function(){
it('redirect to root URL if root is not `/`', function(done){
hexo.config.root = '/test/';

server({$test_mode: true}).then(function(app){
server({}).then(function(app){
hexo.config.root = '/';

request('http://localhost:4000').get('/')
Expand Down

0 comments on commit ffa7a87

Please sign in to comment.