<commit_before>var http = require('http');
var url = require('url');
var Builder = require('./builder');
var runner = require('./runner');

var Argo = function(_http) {
  this._router = {};
  this.builder = new Builder();
  this._http = _http || http;

  var incoming = this._http.IncomingMessage.prototype;
  if (!incoming._modifiedHeaderLine) {
    var _addHeaderLine = incoming._addHeaderLine;

    incoming._modifiedHeaderLine = true;
    incoming._addHeaderLine = function(field, value) {
      this._rawHeaderNames = this._rawHeaderNames || {};
      this._rawHeaderNames[field.toLowerCase()] = field;

      _addHeaderLine.call(this, field, value);
    };
  }
};

Argo.prototype.include = function(mod) {
  var p = mod.package(this);
  p.install();
  return this;
};

Argo.prototype.listen = function(port) {
  runner.listen(this, port);
  return this;
};

Argo.prototype.use = function(middleware) {
  if (middleware.package) {
    return this.include(middleware);
  }
  this.builder.use(middleware);
  return this;
};

Argo.prototype.target = function(url) {
  return this.use(function(addHandler) {
    addHandler('request', function(env, next) {
      env.target.url = url + (env.request.url || '');
      next(env);
    });
  });
};

Argo.prototype.build = function(isNested) {
  var that = this;

  var hasRoutes = false;
  for (var prop in that._router) {
    if (!hasRoutes && that._router.hasOwnProperty(prop)) {
      hasRoutes = true;
    }
  }

  this.builder.use(function(addHandler) {
    addHandler('request', function(env, next) {
      env.argo._http = that._http;
      next(env);
    });
  });
  if (hasRoutes) {
    this.builder.use(function addRouteHandlers(handlers) { 
     that._route(that._router, handlers);
    });
  }

  // spooler
  if (!isNested) {
    this.builder.use(function bufferRequest(handle) {
      handle('request', { hoist: true }, function(env, next) {
        env.request.getBody = function(callback) {
          var start = +Date.now();

          var buf = [];
          var len = 0;
          env.request.on('data', function(chunk) {
            buf.push(chunk);
            len += chunk.length;
          });

          env.request.on('end', function() {
            var body;
            if (buf.length && Buffer.isBuffer(buf[0])) {
              body = new Buffer(len);
              var i = 0;
              buf.forEach(function(chunk) {
                chunk.copy(body, i, 0, chunk.length);
                i += chunk.length;
              });
            } else if (buf.length) {
              body = buf.join('');
            }

            env.request.body = body;

            var duration = (+Date.now() - start);
            //env.printTrace('request spooler', 'Duration (request spooler): ' + duration + 'ms', { duration: duration });

            callback(null, body);
          });
        };
        next(env);
      });

      handle('response', { hoist: true }, function bufferResponse(env, next) {
        if (!env.target.response) {
          next(env);
          return;
        }

        env.response.getBody = function(callback) {
          var start = +Date.now();

          var buf = []; 
          var len = 0;
          env.target.response.on('data', function(chunk) {
            buf.push(chunk);
            len += chunk.length;
          });

          env.target.response.on('end', function() {
            var body;
            if (buf.length && Buffer.isBuffer(buf[0])) {
              body = new Buffer(len);
              var i = 0;
              buf.forEach(function(chunk) {
                chunk.copy(body, i, 0, chunk.length);
                i += chunk.length;
              });
              body = body.toString('binary');
            } else if (buf.length) {
              body = buf.join('');
            }

            env.response.body = body;
            var duration = (+Date.now() - start);
            //env.printTrace('target response', 'Duration (response spooler): ' + duration + 'ms', { duration: duration });

            callback(null, body);
          });
        };

        next(env);
      });
    });
  }

  // Removing tracer for now.  Performance is too slow.
  //
  // if (!isNested) {
  //   that.builder.use(tracer);
  // }

  this.builder.run(that._target);

  if (!isNested) {
    // response ender
    this.builder.use(function(handle) {
      handle('response', { sink: true }, function(env, next) {
        if (!env.response.body && env.response.getBody) {
          env.response.getBody(function(err, body) {
            var body = body || '';
            env.response.setHeader('Content-Length', body.length); 
            env.response.writeHead(env.response.statusCode, env.response.headers);
            env.response.end(body);
          });
          return;
        }
        var body = env.response.body || '';
        env.response.setHeader('Content-Length', body.length); 
        env.response.writeHead(env.response.statusCode, env.response.headers);
        env.response.end(body);
      });
    });
  }

  if (isNested) {
    this.builder.use(function(addHandler) {
      addHandler('request', function(env) {
        if (env.argo.oncomplete) {
          env.argo.oncomplete(env);
        }
      });
    });
  }
  return this.builder.build();
};

Argo.prototype.call = function(env) {
  var app = this.build();
  return app(env);
}

Argo.prototype.route = function(path, options, handlers) {
  if (typeof(options) === 'function') {
    handlers = options;<commit_msg>Fixing bug that caused lost response handlers for mapped components.<commit_after>var http = require('http');
var url = require('url');
var Builder = require('./builder');
var runner = require('./runner');

var Argo = function(_http) {
  this._router = {};
  this.builder = new Builder();
  this._http = _http || http;

  var incoming = this._http.IncomingMessage.prototype;
  if (!incoming._modifiedHeaderLine) {
    var _addHeaderLine = incoming._addHeaderLine;

    incoming._modifiedHeaderLine = true;
    incoming._addHeaderLine = function(field, value) {
      this._rawHeaderNames = this._rawHeaderNames || {};
      this._rawHeaderNames[field.toLowerCase()] = field;

      _addHeaderLine.call(this, field, value);
    };
  }
};

Argo.prototype.include = function(mod) {
  var p = mod.package(this);
  p.install();
  return this;
};

Argo.prototype.listen = function(port) {
  runner.listen(this, port);
  return this;
};

Argo.prototype.use = function(middleware) {
  if (middleware.package) {
    return this.include(middleware);
  }
  this.builder.use(middleware);
  return this;
};

Argo.prototype.target = function(url) {
  return this.use(function(addHandler) {
    addHandler('request', function(env, next) {
      env.target.url = url + (env.request.url || '');
      next(env);
    });
  });
};

Argo.prototype.build = function(isNested) {
  var that = this;

  var hasRoutes = false;
  for (var prop in that._router) {
    if (!hasRoutes && that._router.hasOwnProperty(prop)) {
      hasRoutes = true;
    }
  }

  this.builder.use(function(addHandler) {
    addHandler('request', function(env, next) {
      env.argo._http = that._http;
      next(env);
    });
  });
  if (hasRoutes) {
    this.builder.use(function addRouteHandlers(handlers) { 
     that._route(that._router, handlers);
    });
  }

  // spooler
  if (!isNested) {
    this.builder.use(function bufferRequest(handle) {
      handle('request', { hoist: true }, function(env, next) {
        env.request.getBody = function(callback) {
          var start = +Date.now();

          var buf = [];
          var len = 0;
          env.request.on('data', function(chunk) {
            buf.push(chunk);
            len += chunk.length;
          });

          env.request.on('end', function() {
            var body;
            if (buf.length && Buffer.isBuffer(buf[0])) {
              body = new Buffer(len);
              var i = 0;
              buf.forEach(function(chunk) {
                chunk.copy(body, i, 0, chunk.length);
                i += chunk.length;
              });
            } else if (buf.length) {
              body = buf.join('');
            }

            env.request.body = body;

            var duration = (+Date.now() - start);
            //env.printTrace('request spooler', 'Duration (request spooler): ' + duration + 'ms', { duration: duration });

            callback(null, body);
          });
        };
        next(env);
      });

      handle('response', { hoist: true }, function bufferResponse(env, next) {
        if (!env.target.response) {
          next(env);
          return;
        }

        env.response.getBody = function(callback) {
          var start = +Date.now();

          var buf = []; 
          var len = 0;
          env.target.response.on('data', function(chunk) {
            buf.push(chunk);
            len += chunk.length;
          });

          env.target.response.on('end', function() {
            var body;
            if (buf.length && Buffer.isBuffer(buf[0])) {
              body = new Buffer(len);
              var i = 0;
              buf.forEach(function(chunk) {
                chunk.copy(body, i, 0, chunk.length);
                i += chunk.length;
              });
              body = body.toString('binary');
            } else if (buf.length) {
              body = buf.join('');
            }

            env.response.body = body;
            var duration = (+Date.now() - start);
            //env.printTrace('target response', 'Duration (response spooler): ' + duration + 'ms', { duration: duration });

            callback(null, body);
          });
        };

        next(env);
      });
    });
  }

  // Removing tracer for now.  Performance is too slow.
  //
  // if (!isNested) {
  //   that.builder.use(tracer);
  // }

  this.builder.run(that._target);

  if (!isNested) {
    // response ender
    this.builder.use(function(handle) {
      handle('response', { sink: true }, function(env, next) {
        if (!env.response.body && env.response.getBody) {
          env.response.getBody(function(err, body) {
            var body = body || '';
            env.response.setHeader('Content-Length', body.length); 
            env.response.writeHead(env.response.statusCode, env.response.headers);
            env.response.end(body);
          });
          return;
        }
        var body = env.response.body || '';
        env.response.setHeader('Content-Length', body.length); 
        env.response.writeHead(env.response.statusCode, env.response.headers);
        env.response.end(body);
      });
    });
  }

  if (isNested) {
    this.builder.use(function(addHandler) {
      addHandler('response', { sink: true }, function(env) {
        if (env.argo.oncomplete) {
          env.argo.oncomplete(env);
        }
      });
    });
  }
  return this.builder.build();
};

Argo.prototype.call = function(env) {
  var app = this.build();
  return app(env);
}

Argo.prototype.route = function(path, options, handlers) {
  if (typeof(options) === 'function') {
    handlers = options;
{'fraction_non_alphanumeric': 0.1536448935402382, 'fraction_numerical': 0.001443522194153735, 'mean_word_length': 2.034492198193266, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '838051', 'n_tokens_mistral': 3357, 'n_tokens_neox': 3288, 'n_words': 640}