server.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. 'use strict';
  2. const connect = require('connect');
  3. const http = require('http');
  4. const chalk = require('chalk');
  5. const Promise = require('bluebird');
  6. const open = require('open');
  7. const net = require('net');
  8. const url = require('url');
  9. module.exports = function(args) {
  10. const app = connect();
  11. const { config } = this;
  12. const ip = args.i || args.ip || config.server.ip || undefined;
  13. const port = parseInt(args.p || args.port || config.server.port || process.env.port, 10) || 4000;
  14. const { root } = config;
  15. return checkPort(ip, port).then(() => this.extend.filter.exec('server_middleware', app, {context: this})).then(() => {
  16. if (args.s || args.static) {
  17. return this.load();
  18. }
  19. return this.watch();
  20. }).then(() => startServer(http.createServer(app), port, ip)).then(server => {
  21. const addr = server.address();
  22. const addrString = formatAddress(ip || addr.address, addr.port, root);
  23. this.log.info('Hexo is running at %s . Press Ctrl+C to stop.', chalk.underline(addrString));
  24. this.emit('server');
  25. if (args.o || args.open) {
  26. open(addrString);
  27. }
  28. return server;
  29. }).catch(err => {
  30. switch (err.code) {
  31. case 'EADDRINUSE':
  32. this.log.fatal(`Port ${port} has been used. Try other port instead.`);
  33. break;
  34. case 'EACCES':
  35. this.log.fatal(`Permission denied. You can't use port ${port}.`);
  36. break;
  37. }
  38. this.unwatch();
  39. throw err;
  40. });
  41. };
  42. function startServer(server, port, ip) {
  43. return new Promise((resolve, reject) => {
  44. server.listen(port, ip, resolve);
  45. server.on('error', reject);
  46. }).then(() => server);
  47. }
  48. function checkPort(ip, port) {
  49. if (port > 65535 || port < 1) {
  50. return Promise.reject(new RangeError(`Port number ${port} is invalid. Try a number between 1 and 65535.`));
  51. }
  52. const server = net.createServer();
  53. return new Promise((resolve, reject) => {
  54. server.once('error', reject);
  55. server.once('listening', resolve);
  56. server.listen(port, ip);
  57. }).then(() => { server.close(); });
  58. }
  59. function formatAddress(ip, port, root) {
  60. let hostname = ip;
  61. if (ip === '0.0.0.0' || ip === '::') {
  62. hostname = 'localhost';
  63. }
  64. return url.format({protocol: 'http', hostname: hostname, port: port, path: root});
  65. }