Represents an incoming client request.
@class Request
@constructor
@param {Object} props
@param {String} props.url Request URL
@param {String} props.method Request method ("GET", "POST", ...)
@param {Object} props.headers Request headers
@param {Buffer} props.upgrade Whether or not the request is an
upgrade request
@param {Buffer} props.rawBody Request body, if any
 
Request URL path, including GET parameters (eg. `/foo`,
`/bar/qux`, `/articles?order=date`).

@attribute url
@type String
 
Request method, normalised to uppercase.

@attribute method
@type String
 
Request headers. Note that the header names are Node-style
(ie. lowercase).

@attribute headers
@type Object
 
Request body. Otherwise, `undefined`.

@attribute rawBody
@type Buffer
 
Parsed request body for common content types (could be a
string or an object, depending on the content type). If the
content type is not supported or was unparseable, `body` will
be `null`. JSON bodies and form parameters will become objects,
and plain text and HTML will become strings.

@attribute body
 
Request body parameters.

@attribute bodyParams
@type Object
@deprecated
 
Request query parameters ("GET" parameters).

@attribute queryParams
@type Object
 
Request query parameters ("GET" parameters).

@attribute getParams
@type Object
@deprecated
 
Request URL path captured parameters. Note that this attribute
is only available in request objects passed directly by
RoboHydra, not in user-created request objects.

When defining URL paths, expressions like `:id` or `:user` can
be used as part of the regular expression (eg. `/save/:id` or
`/:user/preferences`). These expressions will match any URL
path fragment, and the matched contents will be available in
the `params` object in the request object. For example, if you
have a head for path `/articles/:articleid/view` and you
receive a request for
`/articles/introduction-to-robohydra/view`, the request object
will have a `params` property with a single property,
`articleid` with value `introduction-to-robohydra`.

@attribute params
@type Object
function Request(props) {
        // From the constructor parameter
        this.url     = props.url;
        this.method  = (props.method || 'GET').toUpperCase();
        this.headers = extendObject({}, props.headers || {});
        this.upgrade = props.upgrade || false;
        this.rawBody = props.rawBody || new Buffer("");
        this.body    = bufferParser.parse(this.rawBody, this.headers);

        // Calculated
        this.queryParams = url.parse(this.url, true).query;
        Object.defineProperty(this, "getParams", {
            get: function() {
                deprecationWarning("'getParams' is deprecated, use 'queryParams' instead");
                return this.queryParams;
            }
        });

        Object.defineProperty(this, "bodyParams", {
            get: function() {
                deprecationWarning("'bodyParams' is deprecated, use 'body' instead");
                try {
                    return qs.parse(this.rawBody.toString());
                } catch (e) {
                    // Ignore, we don't care if the body could not be parsed
                    return null;
                }
            }
        });

        if (this.url === undefined) {
            throw new InvalidRoboHydraRequestException('url', this.url);
        }
    }