var url     = require('url');
var http    = require('http');
var https   = require('https');
var request = require('request');
var copy    = require('request/lib/copy');

/**
 * Return an application url.
 *
 * @param  {Object} app
 * @param  {String} path
 * @return {String}
 */
var serverAddress = function (app, path) {
  // Ensure the passed in path is in string format.
  if (typeof path === 'object') {
    path = url.format(path);
  }

  // If the application url is a string, all direct requests.
  if (typeof app === 'string') {
    return url.resolve(app, path);
  }

  // The application has not been mounted to a port yet, assign a random port.
  if (!app.address()) {
    app.listen(0);
  }

  var port     = app.address().port;
  var protocol = app instanceof https.Server ? 'https' : 'http';

  return url.resolve(protocol + '://localhost:' + port, path);
};

/**
 * Create a request instance for a particular application.
 *
 * @param  {Object}   app
 * @return {Function}
 */
var retest = function (app) {
  /**
   * Returns a function that maps to request expections.
   *
   * @param  {String}   uri
   * @param  {Object}   options
   * @param  {Function} done
   * @return {Object}
   */
  return function (uri, options, done) {
    if (typeof uri === 'undefined') {
      throw new Error('undefined is not a valid uri or options object');
    }

    if (typeof options === 'function' && !done) {
      done = options;
    }

    if (options && typeof options === 'object') {
      options.uri = uri;
    } else if (typeof uri === 'string') {
      options = { uri: uri };
    } else {
      options = uri;
    }

    options = copy(options);

    if (done) {
      options.callback = done;
    }

    // Correct the request uri.
    options.uri = serverAddress(app, options.uri);

    return new request.Request(options);
  };
};

/**
 * Generate an instance of the application for testing with request. Pass a
 * custom request instance as the second parameter.
 *
 * @param  {Object}   app
 * @param  {Object}   opts
 * @return {Function}
 */
exports = module.exports = function (app, opts) {
  if (typeof app === 'function') {
    app = http.createServer(app);
  }

  return request.defaults(opts || {}, retest(app));
};

/**
 * Create a retest agent for keeping cookies.
 *
 * @param  {Object}   app
 * @param  {Object}   opts
 * @return {Function}
 */
exports.agent = function (app, opts) {
  var options = opts ? copy(opts) : {};
  options.jar || (options.jar = request.jar());

  return exports(app, options);
};

@@ -1922,71 +1922,565 @@
 est.
- Pass a%0A * custom request instance as the second parameter.%0A
+%0A *%0A * @param  %7BObject%7D   app%0A * @return %7BFunction%7D%0A */%0Aexports = module.exports = function (app) %7B%0A  if (typeof app === 'function') %7B%0A    app = http.createServer(app);%0A  %7D%0A%0A  var requester = retest(app);%0A  var fn        = request.defaults(%7B%7D, requester);%0A%0A  /**%0A   * Expose the %60defaults%60 function to retest defaults.%0A   *%0A   * @param  %7BObject%7D   opts%0A   * @return %7BFunction%7D%0A   */%0A  fn.defaults = function (opts) %7B%0A    return request.defaults(opts, requester);%0A  %7D;%0A%0A  /**%0A   * Expose the %60forever%60 functionality of request to the retest instance.%0A  
  *%0A
+  
  * @
@@ -2490,35 +2490,46 @@
 am  %7BObject%7D   a
-pp%0A
+gentOptions%0A  
  * @param  %7BObje
@@ -2529,34 +2529,42 @@
   %7BObject%7D   opt
-s%0A
+ionsArg%0A  
  * @return %7BFunc
@@ -2573,101 +2573,239 @@
 on%7D%0A
+  
  */%0A
-exports = module.exports = function (app, opts) %7B%0A  if (typeof app === 'func
+  fn.forever = function (agentOptions, optionsArg) %7B%0A    var options = %7B%7D%0A%0A    if (optionsArg) %7B%0A      for (var option in optionsArg) %7B%0A        options%5Boption%5D = optionsArg%5Boption%5D;%0A      %7D%0A    %7D%0A%0A    if (agentOp
 tion
-'
+s
 ) %7B%0A    
 app 
@@ -2804,59 +2804,96 @@
     
+ 
-app = http.createServer(app);%0A  %7D
+ options.agentOptions = agentOptions;%0A    %7D%0A%0A    options.forever = true;
 %0A%0A  
+ 
+ 
 return 
-request
+fn
 .def
@@ -2905,29 +2905,32 @@
 (opt
-s %7C%7C %7B%7D, retest(app))
+ions);%0A  %7D;%0A%0A  return fn
 ;%0A%7D;
@@ -3207,26 +3207,35 @@
  exports(app
-, 
+).defaults(
 options);%0A%7D;

Add support for additional request methods.