var assert = require('assert');
var http = require('http');
var parse = require('parseurl');
var request = require('./request');
var startProxy = require('./startProxy');

var PORT_HEADER = 'x-koa-whistle-server-port';
var HOST_HEADER = 'x-koa-whistle-host';
var PROXY_HEADER = 'x-koa-whistle-proxy';
var SOCKS_HEADER = 'x-koa-whistle-socks';
var HTTPS_HEADER = 'x-whistle-https-request';
var resolveServer, config, PROXY_REQ_HEADER;
var defer = new Promise(function(resolve) {
  resolveServer = resolve;
});

function checkArgs(headers, value) {
  return headers && value && typeof value === 'string';
}

function setHost(headers, host) {
  if (checkArgs(headers, host)) {
    headers[HOST_HEADER] = host;
  }
}

function setProxy(headers, proxy) {
  if (checkArgs(headers, proxy)) {
    headers[PROXY_HEADER] = proxy;
  }
}

function setSocks(headers, socks) {
  if (checkArgs(headers, socks)) {
    headers[SOCKS_HEADER] = socks;
  }
}

function intercept(req, res) {
  var headers = req.headers;
  if (headers[PROXY_REQ_HEADER]) {
    delete headers[PROXY_REQ_HEADER];
    delete headers[PORT_HEADER];
    delete headers[HTTPS_HEADER];
    return false;
  }

  headers[PORT_HEADER] = config.serverPort;
  headers[PROXY_REQ_HEADER] = 1;
  if (req.secure) {
    headers[HTTPS_HEADER] = 1;
  }
  return defer.then(function(port) {
    var options = parse(req);
    options.headers = req.headers;
    return new Promise(function(resolve, reject) {
      var _req = request(options, port, function(err, _res) {
        if (err) {
          return reject(err);
        }
        resolve(_res);
      });
      _req.on('error', reject);
      req.pipe(_req);
    });
  });
}

exports = module.exports = function (options) {
  if (config) {
    return intercept;
  }
  assert(options, 'argument options is required.');
  assert(options.port > 0, ' Integer argument options.port > 0 is required.');
  assert(options.serverPort > 0, ' Integer argument options.serverPort > 0 is required.');
  assert(options.name && typeof options.name === 'string', 'String argument options.name is required.');
  config = options;
  PROXY_REQ_HEADER = 'x-koa-whistle-' + encodeURIComponent(options.name) + '_' + Date.now();
  var res = startProxy(options);
  res.then(resolveServer).catch(function(err) {
    throw err;
  });
  return intercept;
};

exports.isStarted = function() {
  return !!config;
};

exports.getPortSync = function() {
  return config.port;
};

exports.ready =
  exports.getPort = function() {
    return defer;
  };

exports.createConnection =
  exports.createSocket = function(options) {
    var opts = {
      method: 'CONNECT',
      agent: false
    };
    if (typeof options === 'string') {
      opts.host = options;
      opts.port = arguments[1];
    }
    return new Promise(function(resolve, reject) {
      opts.headers = options.headers || {};
      opts.path = opts.headers.host
        = opts.host + (opts.port > 0 ? ':' + options.port : '');
      defer.then(function(port) {
        opts.host = '127.0.0.1';
        opts.port = port;
        var req = http.request(opts);
        req.once('connect', resolve);
        req.once('error', reject);
        req.end();
      });
    });
  };

exports.setHost = setHost;
exports.setProxy = setProxy;
exports.setSocks = setSocks;

exports.export = function(obj) {
  ['ready', 'getPort', 'isStarted', 'setHost', 'setProxy', 'setSocks',
  'createConnection', 'createSocket'].forEach(function(name) {
    obj[name] = exports[name];
  });
};

@@ -2326,64 +2326,8 @@
 %7D;%0A%0A
-exports.isStarted = function() %7B%0A  return !!config;%0A%7D;%0A%0A
 expo
@@ -3288,21 +3288,8 @@
 rt',
- 'isStarted',
  'se

Refine code