Code coverage report for lib/server.js

Statements: 100% (41 / 41)      Branches: 100% (14 / 14)      Functions: 100% (9 / 9)      Lines: 100% (41 / 41)      Ignored: none     

All files » lib/ » server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 10625                           25 25     25                 25 10 10 6   10     25 10 10 7   10 381 9 9 9     1 1                   25   9     9 4     5 5   5 5 5 5                       25   2     2 1     1 1 1 1 1       25   25  
var http = require('http'),
  mime = require('mime'),
  util = require('util'),
  EventEmitter = require('events').EventEmitter,
  liveReload = require('tiny-lr');
 
/**
 * A static file server designed to support documentation.js's --serve
 * option. It serves from an array of Vinyl File objects (virtual files in
 * memory) and exposes a `setFiles` method that both replaces the set
 * of files and notifies any browsers using LiveReload to reload
 * and display the new content.
 * @class
 */
function Server() {
  this._files = [];
}
 
util.inherits(Server, EventEmitter);
 
/**
 * Update the set of files exposed by this server and notify LiveReload
 * clients
 *
 * @param {Array<File>} files new content. replaces any previously-set content.
 * @returns {Server} self
 */
Server.prototype.setFiles = function (files) {
  this._files = files;
  if (this._lr) {
    this._lr.changed({ body: { files: '*' } });
  }
  return this;
};
 
Server.prototype.handler = function (request, response) {
  var path = request.url.substring(1);
  if (path === '') {
    path = 'index.html';
  }
  for (var i = 0; i < this._files.length; i++) {
    if (this._files[i].relative === path) {
      response.writeHead(200, { 'Content-Type': mime.lookup(path) });
      this._files[i].pipe(response);
      return;
    }
  }
  response.writeHead(404, { 'Content-Type': 'text/plain' });
  response.end('Not found');
};
 
/**
 * Boot up the server's HTTP & LiveReload endpoints. This method
 * can be called multiple times.
 *
 * @param {Function} [callback=] called when server is started
 * @returns {undefined}
 */
Server.prototype.start = function (callback) {
 
  callback = callback || noop;
 
  // idempotent
  if (this._lr) {
    return callback();
  }
 
  this._lr = liveReload();
  this._http = http.createServer(this.handler.bind(this));
 
  this._lr.listen(35729, function () {
    this._http.listen(4001, function () {
      this.emit('listening');
      callback();
    }.bind(this));
  }.bind(this));
};
 
/**
 * Shut down the server's HTTP & LiveReload endpoints. This method
 * can be called multiple times.
 *
 * @param {Function} [callback=] called when server is closed
 * @returns {undefined}
 */
Server.prototype.stop = function (callback) {
 
  callback = callback || noop;
 
  // idempotent
  if (!this._lr) {
    return callback();
  }
 
  this._http.close(function () {
    this._lr.close();
    this._http = null;
    this._lr = null;
    callback();
  }.bind(this));
};
 
function noop() {}
 
module.exports = Server;