function startServer(argv, httpPort, httpsPort, certs) {
  console.log('Launching proxy server...');
  console.log('   http: ' + httpPort);
  console.log('  https: ' + httpsPort);

  // Injects a node stream by buffering all data, transforming it, and writing
  // it back out.
  // Module IDs are assigned on demand and rotate 0-126.
  var nextModuleId = 0;
  function injectStream(url, source, target) {
    var moduleId = nextModuleId++;
    if (nextModuleId >= 127) {
      nextModuleId = 0;
    }
    var sourceCode = '';
    source.on('data', function(chunk) {
      sourceCode += chunk;
    });
    source.on('end', function() {
      try {
        var targetCode = transformCode(moduleId, url, sourceCode, argv);
        target.end(targetCode);
      } catch (e) {
        console.log('Error during transformation, writing through.');
        console.log(e);
        target.end(sourceCode);
      }
    });
  };

  // Handles both HTTP and HTTPS requests.
  function handler(req, res) {
    // Support both the ?url= mode and the X-WTF-URL header.
    var targetUrl;
    if (req.headers['x-wtf-url']) {
      targetUrl = req.headers['x-wtf-url'];
    } else {
      var parsedUrl = url.parse(req.url, true);
      var query = parsedUrl.query;
      targetUrl = query.url;
    }
    if (!targetUrl || targetUrl.indexOf('http') != 0) {
      res.writeHead(404, ['Content-Type', 'text/plain']);
      res.end();
      return;
    }

    res.on('error', function(e) {
      console.log('ERROR (source): ' + e);
    });

    var targetModule = targetUrl.indexOf('https') == 0 ? https : http;
    targetModule.get(targetUrl, function(originalRes) {
      // Eat errors, otherwise the app will die.
      originalRes.on('error', function(e) {
        console.log('ERROR (target): ' + e);
      });

      // Pull out content type to see if we are interested in it.
      var supportedContentType = false;
      var contentType = originalRes.headers['content-type'];
      if (contentType && contentType.indexOf(';') != 0) {
        contentType = contentType.substr(0, contentType.indexOf(';'));
      }
      switch (contentType) {
        case 'text/javascript':
        case 'application/javascript':
          supportedContentType = true;
          break;
      }

      // Also parse the URL - some servers don't return content type for some
      // reason.
      var supportedPath = false;
      var contentUrl = url.parse(targetUrl);
      if (path.extname(contentUrl.pathname) == '.js') {
        supportedPath = true;
      }

      if (supportedContentType || supportedPath) {
        var headers = [];
        for (var key in originalRes.headers) {
          if (key == 'content-length') {
            continue;
          }
          headers.push([key, originalRes.headers[key]]);
        }
        res.writeHead(originalRes.statusCode, headers);
        injectStream(targetUrl, originalRes, res);
      } else {
        console.log('Pass-through: ' + targetUrl, contentType);
        res.writeHead(originalRes.statusCode, originalRes.headers);
        originalRes.pipe(res);
      }
    }).on('error', function(e) {
      console.log(e);
      res.writeHead(404, ['Content-Type', 'text/plain']);
      res.end(e.message);
    });
  };

  // HTTP server.
  var httpServer = http.createServer(handler);
  httpServer.listen(httpPort);

  // HTTPS server.
  var httpsServer = https.createServer({
    key: certs.privateKey,
    cert: certs.certificate
  }, handler);
  httpsServer.listen(httpsPort);

  console.log('Server ready, use ctrl-c to exit...');
  console.log('');
}
Launches a proxy server.
@param {!Object} argv Parsed arguments.
@param {number} httpPort HTTP port.
@param {number} httpsPort HTTPS port.
@param {{privateKey: string, certificate: string}} certs Certificates.