Source: vertx/http.js

/*
 * Copyright 2011-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

if (typeof __vertxload === 'string') {
  throw "Use require() to load Vert.x API modules";
}

/**
 * The http module provides HTTP functions. 
 *
 * @exports vertx/http
 */
var http = {};
var net = require('vertx/net');
var MultiMap = require('vertx/multi_map').MultiMap;
var streams = require('vertx/streams');
var tcp_support = require('vertx/tcp_support');
var ssl_support = require('vertx/ssl_support');
var helpers = require("vertx/helpers.js");
var Buffer = require('vertx/buffer');

/**
 * A <code>BodyHandler</code> is a {@linkcode Handler} that accepts a
 * {@linkcode module:vertx/buffer~Buffer|Buffer} as it's parameter.
 * @typedef {function} BodyHandler
 * @param {module:vertx/buffer~Buffer} buffer A Buffer object containing the body of the message
 */

/**
 * Create and return a {@linkcode module:vertx/http.HttpServer}
 *
 * @example
 * var http = require('vertx/http');
 * var server = http.createHttpServer();
 *
 * // setup request handlers and such...
 * server.listen(8080, 'localhost');
 *
 * @return {module:vertx/http.HttpServer} the newly created server
 */
http.createHttpServer = function() {
  return new http.HttpServer();
};


/**
 * Create and return a {@linkcode module:vertx/http.HttpClient}
 *
 * @returns {module:vertx/http.HttpClient}
 */
http.createHttpClient = function() {
  return new http.HttpClient();
};

/**
 * Represents a server-side HttpServerRequest object. This object is created internally
 * by vert.x and passed as a parameter to a request listener. It should not be directly
 * created.
 *
 * @example
 * var http    = require('vertx/http');
 * var console = require('vertx/console');
 *
 * var server = http.createHttpServer();
 * server.requestHandler(function(request) {
 *
 *   // Get headers from the HttpServerRequest object
 *   // and write them to the console
 *   for (var k in request.headers()) {
 *     console.log(k + ": " + headers[k]);
 *   }
 * 
 *   request.response.end(str);
 * 
 * }).listen(8080, 'localhost');
 *
 * @class 
 * @param {org.vertx.java.core.http.HttpServerRequest} request the underlying
 * Java HttpServerRequest object
 * @augments module:vertx/streams~ReadStream
 */
http.HttpServerRequest = function(jreq) {
  var reqHeaders   = null;
  var reqParams    = null;
  var version      = null;
  var reqFormAttrs = null;
  var netSocket    = null;
  var that         = this;

  /**
   * The HTTP version - either HTTP_1_0 or HTTP_1_1
   *
   * @returns {string} version
   */
  this.version = function() {
    if (version === null) {
      version = jreq.version().toString();
    }
    return version;
  };

  /**
   *
   * Get the NetSocket. Primarily for internal use, but if you really must
   * roll your own websockets or some such, this will let you do that.
   * @returns {module:vertx/net.NetSocket} The raw <code>NetSocket</code>.
   */
  this.netSocket = function() {
    if (netSocket === null) {
      netSocket = new net.NetSocket(jreq.netSocket());
    }
    return netSocket;
  };

  /**
   * The HTTP method, one of HEAD, OPTIONS, GET, POST, PUT, DELETE, CONNECT, TRACE
   *
   * @returns {string} The HTTP method
   */
  this.method = function() {
    return jreq.method();
  };

  /**
   * The uri of the request. For example
   * http://www.somedomain.com/path/morepath/resource.foo?param=32&otherparam=x
   *
   * @returns {string} uri
   */
  this.uri = function() {
    return jreq.uri();
  };

  /**
   * The path part of the uri. For example /path/morepath/resource.foo
   *
   * @returns {string} path
   */
  this.path = function() {
    return jreq.path();
  };

  /**
   * The query part of the uri. For example param=32&otherparam=x
   *
   * @returns {string} query
   */
  this.query = function() {
    return jreq.query();
  };

  /**
   * The headers of the request.
   *
   * @returns {module:vertx/multi_map~MultiMap}
   */
  this.headers = function() {
    if (!reqHeaders) {
      reqHeaders = new MultiMap(jreq.headers());
    }
    return reqHeaders;
  };

  /**
   * Return the remote (client side) address of the request
   *
   * @returns {module:vertx/multi_map~MultiMap}
   */
  this.params = function() {
    if (!reqParams) {
      reqParams = new MultiMap(jreq.params());
    }
    return reqParams;
  };

  /**
   * Get the address of the remote peer. An address object contains
   * port and address properties.
   *
   * @return {} the remote address
   */
  this.remoteAddress = function() {
    return helpers.convertInetSocketAddress(jreq.remoteAddress());
  };


  /**
   * Get the address of the server. An address object contains port
   * and address properties.
   *
   * @return {} the local address.
   */
  this.localAddress = function() {
    return helpers.convertInetSocketAddress(jreq.localAddress());
  };

  /**
   * Get an array of Java X509Certificate objects
   *
   * @return {Array} Array of Java X509Certificate objects
   */
  this.peerCertificateChain = function() {
    return jreq.peerCertificateChain();
  };

  /**
   * Return the absolute URI corresponding to the the HTTP request
   *
   * @returns {string} absoluteURI
   */
  this.absoluteURI = function() {
    return jreq.absoluteURI();
  };

  /**
   * Inform the server that we are expecting a multi-part form.
   * You _must_ call this function _before_ receiving the request
   * body if you expect it to contain a multi-part form.
   *
   * @param {boolean} expect Whether to expect a multi-part form
   * @returns {module:vertx/http.HttpServerRequest} this
   */
  this.expectMultiPart = function(expect) {
    jreq.expectMultiPart(expect);
    return that;
  };

  /**
   * Return a form attributes object
   *
   * @returns {module:vertx/multi_map~MultiMap} The form attributes
   */
  this.formAttributes = function() {
    if (!reqFormAttrs) {
      reqFormAttrs =  new MultiMap(jreq.formAttributes());
    }
    return reqFormAttrs;
  };

  /**
   * Set the upload handler. The handler will get notified once a new file
   * upload was received and so allow to get notified by the upload in
   * progress.
   *
   * @param {UploadHandler} handler The handler to call
   * @returns {module:vertx/http.HttpServerRequest} this
   */
  this.uploadHandler = function(handler) {
    if (handler) {
      jreq.uploadHandler(wrapUploadHandler(handler));
    }
    return that;
  };

  /**
   *  Set the body handler for this request, the handler receives a single
   *  Buffer object as a parameter.  This can be used as a decorator.
   *
   * @param {BodyHandler} handler The handler to call once the body was received
   * @returns {module:vertx/http.HttpServerRequest} this
   */
  this.bodyHandler = function(handler) {
    jreq.bodyHandler(handler);
    return that;
  };

  var jresp = jreq.response();

  /**
   * @property {module:vertx/http.HttpServerResponse} response A response object
   * that can be used to send a response to this request.
   */
  this.response = new http.HttpServerResponse(jresp);

  /**
   * @private
   */
  this._to_java_request = function() {
    return jreq;
  };

  streams.ReadStream.call(this, jreq);

};

/**
 * <p>
 * A server-side HTTP response.
 * An instance of this class is created and associated to every instance of
 * {@linkcode module:vertx/http.HttpServerRequest} that is created.
 * </p>
 *
 * <p>
 * It allows the developer to control the HTTP response that is sent back to
 * the client for a partcular HTTP request. It contains methods that allow HTTP
 * headers and trailers to be set, and for a body to be written out to the
 * response.  
 * </p>
 *
 * @class
 * @param {org.vertx.java.core.http.HttpServerResponse} jresp the underlying java proxy
 * @augments module:vertx/streams~WriteStream
 */
http.HttpServerResponse = function(jresp) {
  var that = this;
  var respHeaders = null;
  var respTrailers = null;

  /**
   * Get or set HTTP status code of the response.
   * @param {number} [code] The HTTP status code, e.g. 200
   * @returns {number|module:vertx/http.HttpServerResponse} If a status code is supplied, this method
   * sets it and returns itself. If a status code is not provided, return the current
   * status code for this response.
   */
  this.statusCode = function(code) {
    if (code) {
      jresp.setStatusCode(code);
      return that;
    } else {
      return jresp.getStatusCode();
    }
  };

  /**
   * Get or set HTTP status message of the response.
   * @param {string} [message] The HTTP status message.
   * @returns {string|module:vertx/http.HttpServerResponse} 
   */
  this.statusMessage = function(msg) {
    if (msg) {
      jresp.setStatusMessage(msg);
      return that;
    } else {
      return jresp.getStatusMessage();
    }
  };

  /**
   * Get or set if the response is chunked
   * @param {boolean} [chunked] Whether or not the response will be chunked encoding
   * @returns {boolean|module:vertx/http.HttpServerResponse}
   */
  this.chunked = function(ch) {
    if (ch) {
      jresp.setChunked(ch);
      return that;
    } else {
      return jresp.isChunked();
    }
  };

  /**
   * Return the http headers of the response
   * @returns {module:vertx/multi_map~MultiMap}
   */
  this.headers = function() {
    if (!respHeaders) {
      respHeaders = new MultiMap(jresp.headers());
    }
    return respHeaders;
  };

  /**
   * Put a header on the response.
   *
   * @param {string} headerName The name under which the header should be stored
   * @param {string} headerValue T the value of the header
   * @returns {module:vertx/http.HttpServerResponse}
   */
  this.putHeader = function(k, v) {
    jresp.putHeader(k, v);
    return that;
  };

  /**
   * Return the trailing headers of the response
   *
   * @returns {module:vertx/multi_map~MultiMap}
   */
  this.trailers = function() {
    if (!respTrailers) {
      respTrailers = new MultiMap(jresp.trailers());
    }
    return respTrailers;
  };

  /**
   * Put a trailing header
   *
   * @param {string} trailerName The name under which the header should be stored
   * @param {string} trailerValue The value of the trailer
   * @returns {module:vertx/http.HttpServerResponse}
   */
  this.putTrailer = function(k, v) {
    jresp.putTrailer(k, v);
    return that;
  };

  /**
   * Write content to the response
   *
   * @param {string} body The body of the response.
   * @param {string} [encoding] The character encoding, defaults to UTF-8
   * @returns {module:vertx/http.HttpServerResponse} Returns self
   */
  this.write = function(body, encoding) {
    if (encoding === undefined) {
      jresp.write(body);
    } else {
      jresp.write(body, encoding);
    }
    return that;
  };

  /**
   * Forces the head of the request to be written before end is called on the
   * request. This is normally used to implement HTTP 100-continue handling,
   * see continue_handler for more information.
   *
   * @returns {module:vertx/http.HttpServerResponse}
   */
  this.sendHead = function() {
    jresp.sendHead();
    return that;
  };

  /**
   * <p>
   * Ends the response. If no data has been written to the response body,
   * the actual response won't get written until this method gets called.
   * </p>
   * <p>
   * Once the response has ended, it cannot be used any more.
   * </p>
   *
   * @param {string} [chunk] a string to write to the data stream before closing
   * @param {string} [encoding] the encoding to use for the write (default is UTF-8)
   */
  this.end = function(arg0, arg1) {
    if (arg0) {
      if (arg1) {
        jresp.end(arg0, arg1);
      } else {
        jresp.end(arg0);
      }
    } else {
      jresp.end();
    }
  };

  /**
   * Tell the kernel to stream a file directly from disk to the outgoing
   * connection, bypassing userspace altogether (where supported by the
   * underlying operating system. This is a very efficient way to serve
   * files.
   *
   * @param {string} fileName Path to file to send.
   * @param {string} [notFoundFile] Path to a file to send if <code>fileName</code> can't be found.
   * @param {ResultHandler} [handler] Function to be called when send has completed (or failed).
   * @returns {module:vertx/http.HttpServerResponse}
   */
  this.sendFile = function(fileName /* arguments */) {
    var args = Array.prototype.slice.call(arguments, 1);
    var notFound = args[0];
    var handler  = args[1];
    if (typeof notFound === 'undefined') {
      notFound = null;
    } else if (typeof notFound === 'function') { 
      handler = notFound;
      notFound = null;
    }
    handler = helpers.adaptAsyncResultHandler(handler);
    jresp.sendFile(fileName, notFound, handler);
    return that;
  };

  streams.WriteStream.call(that, jresp);
};

/**
 * Represents an upload from an HTML form. Created internally and provided to upload
 * handlers. Instances of this class should not be created externally.
 *
 * @constructor
 * @param {org.vertx.java.core.http.HttpServerFileUpload} jupload the underlying java proxy object
 * @see UploadHandler
 * @augments module:vertx/streams~ReadStream
 */
http.HttpServerFileUpload = function(jupload) {
  /**
   * Stream the upload to the given file
   *
   * @param {string} filename The file to which it wil be streamed
   * @returns {http.HttpServerFileUpload}
   */
  this.streamToFileSystem = function(filename) {
    jupload.streamToFileSystem(filename);
    return this;
  };

  /**
   * The filename of the upload
   *
   * @returns {string} filenmae
   */
  this.filename = function() {
    return jupload.filename();
  };

  /**
   * The name of the upload
   *
   * @returns {string} name
   */
  this.name = function() {
    return jupload.name();
  };

  /**
   * The content type
   *
   * @returns {string} contentType
   */
  this.contentType = function() {
    return jupload.contentType();
  };

  /**
   * The content transfer encoding
   *
   * @returns {string} contentTransferEncoding
   */
  this.contentTransferEncoding = function() {
    return jupload.contentTransferEncoding();
  };

  /**
   * The charset
   *
   * @returns {string} charset
   */
  this.charset = function() {
    return jupload.charset().toString();
  };

  /**
   * The size
   *
   * @returns {number} size
   */
  this.size = function() {
    return jupload.size();
  };

  streams.ReadStream.call(this, jupload);
};

/**
 * An <code>UploadHandler</code> is a {@linkcode Handler} that accepts a
 * {@linkcode module:vertx/http.HttpServerFileUpload|HttpServerFileUpload} 
 * object as it's parameter. This allows server code to handle and process
 * uploaded files from HTTP clients.
 * @typedef {function} UploadHandler
 * @param {module:vertx/http.HttpServerFileUpload} upload The file being uploaded
 */
var wrapUploadHandler = function(handler) {
  return function(jupload) {
    handler(new http.HttpServerFileUpload(jupload));
  };
};

/**
 * <p>Represents an HTML 5 Websocket</p>
 * <p>Instances of this class are created and provided to the handler of an
 * {@linkcode HttpClient} when a successful websocket connect attempt occurs.</p>
 * <p>It implements both {@linkcode ReadStream} and {@linkcode WriteStream} so
 * it can be used with {@linkcode module:vertx/Pump~Pump|Pump} to pump data
 * with flow control.</p>
 *
 * @constructor
 *
 * @param {org.vertx.java.core.http.WebSocketBase} jWebSocket The java WebSocketBase object
 * @param {boolean} [server] whether this is a server-side websocket (default: false)
 * @see WebSocketHandler
 * @augments module:vertx/streams~ReadStream
 * @augments module:vertx/streams~WriteStream
 */
http.WebSocket = function(jwebsocket, server) {
  var headers = null;

  /**
   * When a WebSocket is created it automatically registers an event handler
   * with the eventbus, the ID of that handler is returned.
   *
   * Given this ID, a different event loop can send a binary frame to that
   * event handler using the event bus and that buffer will be received by
   * this instance in its own event loop and written to the underlying
   * connection. This allows you to write data to other websockets which are
   * owned by different event loops.
   *
   * @returns {string} id
   */
  this.binaryHandlerID = function() {
    return jwebsocket.binaryHandlerID();
  };

  /**
   * When a WebSocket is created it automatically registers an event handler
   * with the eventbus, the ID of that handler is returned.
   *
   * Given this ID, a different event loop can send a text frame to that
   * event handler using the event bus and that buffer will be received by
   * this instance in its own event loop and written to the underlying
   * connection. This allows you to write data to other websockets which are
   * owned by different event loops.
   *
   * @returns {string} id
   */
  this.textHandlerID = function() {
    return jwebsocket.textHandlerID();
  };

  /**
   *  Write data to the websocket as a binary frame
   *
   * @param {module:vertx/buffer~Buffer} data
   */
  this.writeBinaryFrame = function(data) {
    jwebsocket.writeBinaryFrame(data._to_java_buffer());
  };

  /**
   *  Write data to the websocket as a text frame
   *
   * @param {module:vertx/buffer~Buffer} data
   */
  this.writeTextFrame = function(data) {
    jwebsocket.writeTextFrame(data);
  };

  /**
   * Set a closed {@linkcode Handler} on the connection, the handler receives
   * no parameters.
   *
   * @param {Handler} handler The handler to call when the underlying connection has been closed
   * @returns {WebSocket} this
   */
  this.closeHandler = function(handler) {
    jwebsocket.closeHandler(handler);
    return this;
  };

  /**
   * Close the websocket connection
   */
  this.close = function() {
    jwebsocket.close();
  };

  if (server) {
    /**
     * The path the websocket connect was attempted at.
     * Only available if this is a server websocket.
     *
     * @returns {string} path
     */
    this.path = function() {
      return jwebsocket.path();
    };

    /**
     * Reject the WebSocket. Sends 404 to client
     * Only available if this is a server websocket.
     *
     * @returns {module:vertx/http.WebSocket}
     */
    this.reject = function() {
      jwebsocket.reject();
      return ws;
    };
    /**
     * The headers of the handshake request
     * Only available if this is a server websocket.
     *
     * @returns {module:vertx/multi_map~MultiMap}
     */
    this.headers = function() {
      if (!headers) {
        headers = new MultiMap(jwebsocket.headers());
      }
      return headers;
    };

    /**
     * The URI the websocket handshake occured at
     * @returns {string}
     */
    this.uri = function() {
      return jwebsocket.uri();
    };
  }
  streams.WriteStream.call(this, jwebsocket);
  streams.ReadStream.call(this, jwebsocket);
};

/**
 * An HTTP and websockets server. Created by calling 
 * {@linkcode module:vertx/http.createHttpServer}.
 *
 * @example
 * var http = require('vertx/http');
 * var server = http.createHttpServer();
 *
 * server.requestHandler( function(request) {
 *    // handle the incoming request
 * }
 *
 * server.listen(8000, 'localhost');
 *
 * @class
 * @augments module:vertx/tcp_support~TCPSupport
 * @augments module:vertx/tcp_support~ServerTCPSupport
 * @augments module:vertx/ssl_support~SSLSupport
 * @augments module:vertx/ssl_support~ServerSSLSupport
 */
http.HttpServer = function() {
  var that = this;
  var jserver = __jvertx.createHttpServer();

  tcp_support.TCPSupport.call(this, jserver);
  tcp_support.ServerTCPSupport.call(this, jserver);

  ssl_support.SSLSupport.call(this, jserver);
  ssl_support.ServerSSLSupport.call(this, jserver);

  /**
   * Set the request handler for the server. As HTTP requests are received by
   * the server, instances of 
   * {@linkcode module:vertx/http.HttpServerRequest|HttpServerRequest} will be created
   * and passed to this handler.
   *
   * @param {RequestHandler} handler the function used to handle the request.
   * @return {module:vertx/http.HttpServer}
   */
  this.requestHandler = function(handler) {
    if (handler) {
      if (typeof handler === 'function') {
        handler = wrappedRequestHandler(handler);
      } else {
        // It's a route matcher
        handler = handler._to_java_handler();
      }
      jserver.requestHandler(handler);
    }
    return that;
  };

  /**
   * Set the websocket handler for the server. If a websocket connect
   * handshake is successful a new 
   * {@linkcode module:vertx/http.WebSocket|WebSocket} instance will be created
   * and passed to the handler.
   * 
   * @param {WebSocketHandler} handler the function used to handle the request.
   * @return {module:vertx/http.HttpServer}
   */
  this.websocketHandler = function(handler) {
    if (handler) {
      jserver.websocketHandler(wrappedWebsocketHandler(true, handler));
    }
    return that;
  };

  /**
   * Set or get whether the server should compress the http response if the
   * connected client supports it.
   * @param {boolean} [supported] whether compression should be supported when possible
   * @return {boolean|module:vertx/http.HttpServer} the current server configuration or self
   */
  this.compressionSupported = function(bool) {
    if (bool) {
      jserver.setCompressionSupported(bool);
      return that;
    }
    return jserver.isCompressionSupported();
  };

  /**
   * Set or get the maximum frame size for websocket connections exposed
   * over the SockJS bridge with this HTTPServer
   * @param {number} [size] The frame size in bytes
   */
  this.maxWebSocketFrameSize = function(size) {
    if (size) {
      jserver.setMaxWebSocketFrameSize(size);
      return that;
    }
    return jserver.getMaxWebSocketFrameSize();
  };

  /**
   * Close the server. If a handler is supplied, it will be called
   * when the underlying connection has completed closing.
   *
   * @param {Handler} [handler] The handler to notify when close() completes
   */
  this.close = function(handler) {
    if (handler) {
      jserver.close(handler);
    } else {
      jserver.close();
    }
  };

  /**
   * Start to listen for incoming HTTP requests
   *
   * @param {number} port The port to listen on
   * @param {string} [host] The host name or IP address
   * @param {Handler} [listenHandler] A handler to be notified when the underlying
   *        system level listen() call has completed.
   * @returns {module:vertx/http.HttpServer}
   */
  this.listen = function() {
    var args = Array.prototype.slice.call(arguments);
    var handler = helpers.getArgValue('function', args);
    var host = helpers.getArgValue('string', args);
    var port = helpers.getArgValue('number', args);
    if (handler) {
      handler = helpers.adaptAsyncResultHandler(handler);
    }
    if (host === null) {
      host = "0.0.0.0";
    }
    jserver.listen(port, host, handler);
    return that;
  };

  /**
   * @private
   */
  this._to_java_server = function() {
    return jserver;
  };
};


/**
 * <p>An HTTP client that maintains a pool of connections to a specific host, at a
 * specific port. The client supports pipelining of requests.</p>
 * <p>As well as HTTP requests, the client can act as a factory for 
 * HTML5 {@linkcode module:vertx/http.WebSocket|websockets}.</p>
 *
 * @class
 * @augments module:vertx/tcp_support~TCPSupport
 * @augments module:vertx/ssl_support~SSLSupport
 * @augments module:vertx/ssl_support~ClientSSLSupport
 */
http.HttpClient = function() {
  var that = this;
  var jclient = __jvertx.createHttpClient();

  tcp_support.TCPSupport.call(this, jclient);

  ssl_support.SSLSupport.call(this, jclient);
  ssl_support.ClientSSLSupport.call(this, jclient);
  /**
   * Set the exception handler.
   *
   * @param {Handler} handler The handler which is called on an exception
   * @returns {module:vertx/http.HttpClient}
   */
  this.exceptionHandler = function(handler) {
    jclient.exceptionHandler(handler);
    return that;
  };

  /**
   * Get or set the maxium number of connections this client will pool
   *
   * @param {number} [size] the maximum number of connection
   * @returns {number|module:vertx/http.HttpClient}
   */
  this.maxPoolSize = function(size) {
    if (size === undefined) {
      return jclient.getMaxPoolSize();
    } else {
      jclient.setMaxPoolSize(size);
      return that;
    }
  };

  /**
   * Set or get the maximum frame size for websocket connections exposed
   * over the SockJS bridge with this HTTPClient
   * @param {number} [size] The frame size in bytes
   */
  this.maxWebSocketFrameSize = function(size) {
    if (size) {
      jclient.setMaxWebSocketFrameSize(size);
      return that;
    }
    return jclient.getMaxWebSocketFrameSize();
  };

  /**
   * Set or get whether the client should try to use compression
   * @param {boolean} [shouldTry] Whether the client should try to use compression
   * @return {boolean|module:vertx/http.HttpClient} Whether compression is tried or self
   */
  this.tryUseCompression = function(shouldTry) {
    if (shouldTry) {
      jclient.setTryUseCompression(shouldTry);
      return that;
    }
    return jclient.getTryUseCompression();
  };

  /**
   * <p>
   * Get or set if the client use keep alive. If <code>keepAlive</code> is
   * <code>true</code> then, after the request has ended the connection will be
   * returned to the pool where it can be used by another request. In this
   * manner, many HTTP requests can be pipe-lined over an HTTP connection.
   * Keep alive connections will not be closed until the <code>close()</code>
   * method is invoked.</p>
   * <p>
   * If <code>keepAlive</code> is <code>false</code> then a new connection will
   * be created for each request and it won't ever go in the pool, and the
   * connection will closed after the response has been received. Even with no
   * keep alive, the client will not allow more than <code>getMaxPoolSize()</code>
   * connections to be created at any one time.</p> 
   * <p>
   * If <code>keepAlive</code> is <code>undefined</code> returns the current
   * keep alive status of this client.
   * </p>
   *
   * @param {boolean} [keepAlive]
   * @returns {boolean|module:vertx/http.HttpClient}
   */
  this.keepAlive = function(ka) {
    if (ka === undefined) {
      return jclient.isKeepAlive();
    } else {
      jclient.setKeepAlive(ka);
      return that;
    }
  };

  /**
   * Get or set the port that the client will attempt to connect to on the
   * server on. The default value is 80 
   *
   * @param {number} [port] The port to connect on.
   * @returns {number|module:vertx/http.HttpClient}
   */
  this.port = function(p) {
    if (p === undefined) {
      return jclient.getPort();
    } else {
      jclient.setPort(p);
      return that;
    }
  };

  /**
   *  Get or set the host name or ip address that the client will attempt to
   *  connect to on the server on
   *
   * @param {string} [host] The host name or IP address.
   * @returns {string|module:vertx/http.HttpClient}
   */
  this.host = function(h) {
    if (h === undefined) {
      return jclient.getHost();
    } else {
      jclient.setHost(h);
      return that;
    }
  };

  /**
   * Get or set if the host should be verified.  If set then the client will
   * try to validate the remote server's certificate hostname against the
   * requested host. Should default to 'true'.
   * This method should only be used in SSL mode
   *
   * @param {boolean} verify whether or not to verify hosts 
   * @returns {boolean|module:vertx/http.HttpClient}
   */
  this.verifyHost = function(h) {
    if (h === undefined) {
      return jclient.isVerifyHost();
    } else {
      jclient.setVerifyHost(h);
      return that;
    }
  };

  /**
   * Attempt to connect an HTML5 websocket to the specified URI.
   * The connect is done asynchronously and the handler is called with a WebSocket on success.
   *
   * @param {string} uri A relative URI where to connect the websocket on the host, e.g. /some/path
   * @param {WebSocketHandler} handler The handler to be called with the WebSocket
   */
  this.connectWebsocket = function(uri, handler) {
    jclient.connectWebsocket(uri, wrappedWebsocketHandler(false, handler));
  };

  /**
   * This is a quick version of the get method where you do not want to do anything with the request
   * before sing.
   * With this method the request is immediately sent.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the GET on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.getNow = function(uri, handler) {
    return new http.HttpClientRequest(jclient.getNow(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP OPTIONS request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the OPTIONS on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.options = function(uri, handler) {
    return new http.HttpClientRequest(jclient.options(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP GET request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the GET on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.get =function(uri, handler) {
    return new http.HttpClientRequest(jclient.get(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP HEAD request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the HEAD on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.head =function(uri, handler) {
    return new http.HttpClientRequest(jclient.head(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP POST request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the POST on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.post = function(uri, handler) {
    return new http.HttpClientRequest(jclient.post(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP PUT request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the PUT on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.put = function(uri, handler) {
    return new http.HttpClientRequest(jclient.put(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP DELETE request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the DELETE on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.delete = function(uri, handler) {
    return new http.HttpClientRequest(jclient.delete(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP TRACE request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the TRACE on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.trace = function(uri, handler) {
    return new http.HttpClientRequest(jclient.trace(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP CONNECT request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the CONNECT on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.connect = function(uri, handler) {
    return new http.HttpClientRequest(jclient.connect(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP PATCH request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} uri A relative URI where to perform the PATCH on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.patch = function(uri, handler) {
    return new http.HttpClientRequest(jclient.patch(uri, wrapResponseHandler(handler)));
  };

  /**
   * This method returns an request which represents an HTTP request with the specified uri.
   * When an HTTP response is received from the server the handler is called passing in the response.
   *
   * @param {string} method The HTTP method which is used for the request
   * @param {string} uri A relative URI where to perform the PUT on the server.
   * @param {ResponseHandler} handler The handler to be called
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.request = function(method, uri, handler) {
    return new http.HttpClientRequest(jclient.request(method, uri, wrapResponseHandler(handler)));
  };

  /**
   * Close the client
   */
  this.close = function() {
    jclient.close();
  };

  /**
   * A <code>ResponseHandler</code> is a {@linkcode Handler} that accepts a
   * {@linkcode module:vertx/http.HttpClientResponse|ClientResponse} 
   * object as it's parameter. 
   * @typedef {function} ResponseHandler
   * @param {module:vertx/http.HttpClientResponse} response The HTTP client response
   */
  var wrapResponseHandler = function(handler) {
    return function(jresp) {
      handler(new http.HttpClientResponse(jresp));
    };
  };

};

/**
 * <p>
 * Represents a client-side HTTP request.  Instances are created by an
 * {@linkcode module:vertx/http.HttpClient} instance, via one of the methods
 * corresponding to the specific HTTP methods, or the generic {@linkcode
 * module:vertx/http.HttpClient#request} method.
 * </p>
 * <p>
 * Once a request has been obtained, headers can be set on it, and data can be
 * written to its body if required. Once you are ready to send the request, the
 * {@linkcode module:vertx/http.HttpClientRequest#end} method should be called.
 * </p>
 * <p>
 * The headers of the request are actually sent either when the 
 * {@linkcode module:vertx/http.HttpClientRequest#end} method is called, or,
 * when the first part of the body is written, whichever
 * occurs first.
 * </p>
 * <p>
 * This class supports both chunked and non-chunked HTTP.
 * It mixes in {@linkcode module:vertx/streams~WriteStream} so it can be used with
 * {@linkcode module:vertx/pump~Pump} to pump data with flow control.
 * </p>
 * <p>
 * An example of using this class is as follows:
 * <p>
 *
 * @example
 *
 * var console = require('vertx/console');
 *
 * var req = httpClient.post("/some-url", function(response) {
 *     console.log("Got response: " + response.statusCode);
 *   }
 * });
 *
 * req.headers().add("Content-Length", 5);
 * req.end(new Buffer('hello');
 *
 * @constructor
 * @param org.vertx.java.core.http.HttpClientRequest the underlying Java proxy
 * @augments module:vertx/streams~WriteStream
 */
http.HttpClientRequest = function(jreq) {
  var that = this;
  var reqHeaders = null;

  /**
   * Sets or gets whether the request should used HTTP chunked encoding or not.
   *
   * @param {boolean} [chunked] If val is true, this request will use HTTP
   * chunked encoding, and each call to write to the body will correspond to a
   * new HTTP chunk sent on the wire. If chunked encoding is used the HTTP
   * header 'Transfer-Encoding' with a value of 'Chunked' will be automatically
   * inserted in the request. If <code>chunked</code> is not provided, returns
   * the current value.
   * @returns {boolean|module:vertx/http.HttpClientRequest}
   */
  this.chunked = function(ch) {
    if (ch === undefined) {
      return jreq.isChunked();
    } else {
      jreq.setChunked(ch);
      return that;
    }
  };

  /**
   * Returns the headers for the requests
   *
   * @returns {module:vertx/multi_map~MultiMap} The headers
   */
  this.headers = function() {
    if (!reqHeaders) {
      reqHeaders = new MultiMap(jreq.headers());
    }
    return reqHeaders;
  };

  /**
   * Put a header on the request
   *
   * @param {string} name The header name
   * @param {string} value The header value
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.putHeader = function(k, v) {
    jreq.putHeader(k, v);
    return that;
  };

  /**
   * Write to the request body
   * @param {string} chunk the data to write
   * @param {string} [encoding] the data encoding (default is UTF-8)
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.write = function(arg0, arg1) {
    if (arg1 === undefined) {
      jreq.write(arg0);
    } else {
      jreq.write(arg0, arg1);
    }
    return that;
  };

  /**
   * If you send an HTTP request with the header 'Expect' set to the value
   * '100-continue' and the server responds with an interim HTTP response with
   * a status code of '100' and a continue handler has been set using this
   * method, then the handler will be called.  You can then continue to write
   * data to the request body and later end it. This is normally used in
   * conjunction with the send_head method to force the request header to be
   * written before the request has ended.
   *
   * @param {Handler} handler The handler
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.continueHandler = function(handler) {
    jreq.continueHandler(handler);
    return that;
  };

  /**
   * Forces the head of the request to be written before end is called on the
   * request. This is normally used to implement HTTP 100-continue handling.
   *
   * @see module:vertx/http.HttpClientRequest#continue_handler
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.sendHead = function() {
    jreq.sendHead();
    return that;
  };

  /**
   * Ends the request. If no data has been written to the request body, and
   * send_head has not been called then the actual request won't get written
   * until this method gets called.  Once the request has ended, it cannot be
   * used any more, and if keep alive is true the underlying connection will
   * be returned to the HttpClient pool so it can be assigned to another request.
   *
   * @param {string} [chunk] The data to write
   * @param {string} [encoding] The charset to use if data is written
   */
  this.end = function(arg0, arg1) {
    if (arg0) {
      if (arg1) {
        jreq.end(arg0, arg1);
      } else {
        jreq.end(arg0);
      }
    } else {
      jreq.end();
    }
  };

  /**
   * Set's the amount of time after which if a response is not received an exception
   * will be sent to the exception handler of this request. Calling this method more than once
   * has the effect of canceling any existing timeout and starting the timeout from scratch.
   *
   * @param {number} timeout The amount of time in milliseconds to wait before timing out
   * @returns {module:vertx/http.HttpClientRequest}
   */
  this.timeout = function(t) {
    jreq.setTimeout(t);
    return that;
  };
  streams.WriteStream.call(this, jreq);
};

/**
 * <p>Represents a client-side HTTP response.
 * An instance is provided to the user via a {@linkcode ResponseHandler}
 * instance that was specified when one of the HTTP method operations, or the
 * generic {@linkcode module:vertx.http.HttpClient#request|request}
 * method was called on an instance of {@linkcode module:vertx/http.HttpClient}.
 * </p>
 * <p>
 * It mixes in {@linkcode module:vertx/streams~ReadStream} so it can be used with
 * {@linkcode module:vertx/pump~Pump|Pump} to pump data with flow control.
 * </p>
 * @constructor
 * @param {org.vertx.java.core.http.HttpClientResponse} jresp the underlying Java proxy
 * @see ResponseHandler
 * @augments module:vertx/streams~ReadStream
 */
http.HttpClientResponse = function(jresp) {
  var that = this;
  var respHeaders = null;
  var respTrailers = null;
  var netSocket    = null;

  /**
   *
   * Get the NetSocket. Primarily for internal use, but if you really must
   * roll your own websockets or some such, this will let you do that.
   * @returns {module:vertx/net.NetSocket} The raw <code>NetSocket</code>.
   */
  this.netSocket = function() {
    if (netSocket === null) {
      netSocket = new net.NetSocket(jresp.netSocket());
    }
    return netSocket;
  };

  /**
   * The HTTP status code of the response.
   *
   * @returns {number} The HTTP Status code
   */
  this.statusCode = function() {
    return jresp.statusCode();
  };

  /**
   * The HTTP Status message of the response
   *
   * @returns {string} The HTTP Status message
   */
  this.statusMessage = function() {
    return jresp.statusMessage();
  };

  /**
   * Get all the headers of the response.
   *
   * @returns {module:vertx/multi_map~MultiMap} The response headers
   */
  this.headers = function() {
    if (!respHeaders) {
      respHeaders = new MultiMap(jresp.headers());
    }
    return respHeaders;
  };

  /**
   * Get all the trailing headers of the response.
   *
   * @returns {module:vertx/multi_map~MultiMap} The response trailers
   */
  this.trailers = function() {
    if (!respTrailers) {
      respTrailers = new MultiMap(jresp.trailers());
    }
    return respTrailers;
  };

  /**
    * The Set-Cookie headers (including trailers)
   *
   * @returns {Array} The cookies as an array of strings
   */
  this.cookies = function() {
    return jresp.cookies();
  };

  /**
   * Set a handler to receive the entire body in one go - do not use this for large bodies
   *
   * @param {BodyHandler} handler The handler to use
   * @returns {module:vertx/http.HttpClientResponse}
   */
  this.bodyHandler = function(handler) {
    jresp.bodyHandler(function(buffer) {
      handler(new Buffer(buffer));
    });
    return that;
  };
  streams.ReadStream.call(this, jresp);
};


/**
 * <p>
 * This class allows you to do route requests based on the HTTP verb and the
 * request URI, in a manner similar to <a * href="http://www.sinatrarb.com/">Sinatra</a> 
 * or <a * href="http://expressjs.com/">Express</a>.
 * RouteMatcher also lets you extract paramaters from the request URI either a
 * simple pattern or using regular expressions for more complex matches. Any
 * parameters extracted will be added to the requests parameters
 * which will be available to you in your request handler.
 * </p>
 * <p>
 * It's particularly useful when writing REST-ful web applications.
 * </p>
 *
 * <p>
 * To use a simple pattern to extract parameters simply prefix the parameter
 * name in the pattern with a ':' (colon).
 * </p>
 *
 * <p>
 * Different handlers can be specified for each of the HTTP verbs, GET, POST, PUT, DELETE etc.
 * </p>
 *
 * <p>
 * For more complex matches regular expressions can be used in the pattern.
 * When regular expressions are used, the extracted parameters do not have a
 * name, so they are put into the HTTP request with names of param0, param1,
 * param2 etc.
 * </p>
 *
 * Multiple matches can be specified for each HTTP verb. In the case there are
 * more than one matching patterns for a particular request, the first matching
 * one will be used.
 *
 * @example
 * var http = require('vertx/http');
 * var server = http.createHttpServer();
 * 
 * var routeMatcher = new http.RouteMatcher();
 * 
 * routeMatcher.get('/animals/dogs', function(req) {
 *     req.response.end('You requested dogs');
 * });
 * 
 * routeMatcher.get('/animals/cats', function(req) {
 *     req.response.end('You requested cats');    
 * });
 * 
 * server.requestHandler(routeMatcher).listen(8080, 'localhost');
 *
 * @constructor
 */
http.RouteMatcher = function() {

  var j_rm = new org.vertx.java.core.http.RouteMatcher();

  // req_map keeps track of all JavaScript requests while the corresponding
  // Java request traverses j_rm. We do this in order to pass any JavaScript
  // request passed to this.call() unmodified to the route handlers in case
  // the user has augmented the request.
  var req_map = new java.util.HashMap();

  function req_map_wrappedRequestHandler(handler) {
    var wrappedHandler = wrappedRequestHandler(handler);
    return function(jreq) {
      var req = req_map.remove(jreq);
      if (req) {
        return handler(req);
      } else {
        return wrappedHandler(jreq);
      }
    };
  }

  this.call = function(req) {
    var jreq = req._to_java_request();
    req_map.put(jreq, req);
    j_rm.handle(jreq);
  };

  /**
   * Specify a handler that will be called for a matching HTTP GET
   *
   * @pattern {string} pattern to match
   * @param {RequestHandler} handler handler for match
   * @return {module:vertx/http.RouteMatcher}
   */
  this.get = function(pattern, handler) {
    j_rm.get(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP PUT
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.put = function(pattern, handler) {
    j_rm.put(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP POST
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.post = function(pattern, handler) {
    j_rm.post(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP DELETE
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.delete = function(pattern, handler) {
    j_rm.delete(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP OPTIONS
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.options = function(pattern, handler) {
    j_rm.options(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP HEAD
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.head = function(pattern, handler) {
    j_rm.head(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP TRACE
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.trace = function(pattern, handler) {
    j_rm.trace(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP CONNECT
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.connect = function(pattern, handler) {
    j_rm.connect(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP PATCH
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.patch = function(pattern, handler) {
    j_rm.patch(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP ALL
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.all = function(pattern, handler) {
    j_rm.all(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP GET
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}

   */
  this.getWithRegEx = function(pattern, handler) {
    j_rm.getWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP PUT
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.putWithRegEx = function(pattern, handler) {
    j_rm.putWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP POST
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.postWithRegEx = function(pattern, handler) {
    j_rm.postWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP DELETE
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.deleteWithRegEx = function(pattern, handler) {
    j_rm.deleteWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP PUT
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.optionsWithRegEx = function(pattern, handler) {
    j_rm.optionsWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP HEAD
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.headWithRegEx = function(pattern, handler) {
    j_rm.headWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP TRACE
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.traceWithRegEx = function(pattern, handler) {
    j_rm.traceWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP CONNECT
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.connectWithRegEx = function(pattern, handler) {
    j_rm.connectWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP PATCH
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.patchWithRegEx = function(pattern, handler) {
    j_rm.patchWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for a matching HTTP request
   *
   * @param {string} pattern pattern to match
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.allWithRegEx = function(pattern, handler) {
    j_rm.allWithRegEx(pattern, req_map_wrappedRequestHandler(handler));
    return this;
  };

  /**
   * Specify a handler that will be called for HTTP request that not match any pattern.
   *
   * @param {RequestHandler} handler http server request handler
   * @return {module:vertx/http.RouteMatcher}
   */
  this.noMatch = function(handler) {
    j_rm.noMatch(req_map_wrappedRequestHandler(handler));
    return this;
  };
  /**
   *
   * @returns {org.vertx.java.core.http.RouteMatcher}
   * @private
   */
  this._to_java_handler = function() {
    return j_rm;
  };

  /**
   * For testing.
   * @returns the map of JavaScript requests where the corresponding Java
   * request was passed to the Java RouteMatcher and has yet to return.
   * @private
   */
  this._requests_in_limbo_map = function() {
    return req_map;
  };

  // Regster default noMatchHandler to remove references from req_map.
  this.noMatch(function(req) {
    req.response.statusCode(404).end();
  });
};


/**
 * A <code>WebSocketHandler</code> is a {@linkcode Handler} that accepts a
 * {@linkcode module:vertx/http.WebSocket|WebSocket} as it's parameter.
 *
 * @typedef {function} WebSocketHandler
 * @param {module:vertx/http.WebSocket} websocket the active {@linkcode module:vertx/http.WebSocket|WebSocket}
 */
function wrappedWebsocketHandler(server, handler) {
  return function(jwebsocket) {
    handler(new http.WebSocket(jwebsocket, server));
  };
}

/**
 * A <code>RequestHandler</code> is a {@linkcode Handler} that responds to
 * notifications from objects in the <code>vertx/http</code> module and expects
 * an {@linkcode module:vertx/http.HttpServerRequest|HttpServerRequest} object
 * as its parameter.
 *
 * @example
 * var http = require('vertx/http');
 * var server = http.createHttpServer();
 *
 * server.requestHandler( function( request ) {
 *   // This function is executed for each
 *   // request event on our server
 * } );
 *
 * @see module:vertx/http.HttpServer#requestHandler
 * @typedef {function} RequestHandler
 * @param {message} request The incoming message
 */
function wrappedRequestHandler(handler) {
  return function(jreq) {
    handler(new http.HttpServerRequest(jreq));
  };
}

module.exports = http;