function redirect(arg1, arg2, arg3) {
        var self = this;
        var statusCode = 302;
        var finalUri;
        var redirectLocation;
        var next;

        // 1) this is signature 1, where an explicit status code is passed in.
        //    MUST guard against null here, passing null is likely indicative
        //    of an attempt to call res.redirect(null, next);
        //    as a way to do a reload of the current page.
        if (arg1 && !isNaN(arg1)) {
            statusCode = arg1;
            finalUri = arg2;
            next = arg3;
        } else if (typeof arg1 === 'string') {
            // 2) this is signaure number 2
            // otherwise, it's a string, and use it directly
            finalUri = arg1;
            next = arg2;
        } else if (typeof arg1 === 'object') {
            // 3) signature number 3, using an options object.
            // set next, then go to work.
            next = arg2;

            var req = self.req;
            var opt = arg1 || {};
            var currentFullPath = req.href();
            var secure = opt.hasOwnProperty('secure')
                ? opt.secure
                : req.isSecure();

            // if hostname is passed in, use that as the base,
            // otherwise fall back on current url.
            var parsedUri = url.parse(opt.hostname || currentFullPath, true);

            // create the object we'll use to format for the final uri.
            // this object will eventually get passed to url.format().
            // can't use parsedUri to seed it, as it confuses the url module
            // with some existing parsed state. instead, we'll pick the things
            // we want and use that as a starting point.
            finalUri = {
                port: parsedUri.port,
                hostname: parsedUri.hostname,
                query: parsedUri.query,
                pathname: parsedUri.pathname
            };

            // start building url based on options.
            // start with the host
            if (opt.hostname) {
                finalUri.hostname = opt.hostname;
            }

            // then set protocol IFF hostname is set - otherwise we end up with
            // malformed URL.
            if (finalUri.hostname) {
                finalUri.protocol = secure === true ? 'https' : 'http';
            }

            // then set current path after the host
            if (opt.pathname) {
                finalUri.pathname = opt.pathname;
            }

            // then set port
            if (opt.port) {
                finalUri.port = opt.port;
            }

            // then add query params
            if (opt.query) {
                if (opt.overrideQuery === true) {
                    finalUri.query = opt.query;
                } else {
                    finalUri.query = utils.mergeQs(opt.query, finalUri.query);
                }
            }

            // change status code to 301 permanent if specified
            if (opt.permanent) {
                statusCode = 301;
            }
        }

        // if we're missing a next we should probably throw. if user wanted
        // to redirect but we were unable to do so, we should not continue
        // down the handler stack.
        assert.func(next, 'res.redirect() requires a next param');

        // if we are missing a finalized uri
        // by this point, pass an error to next.
        if (!finalUri) {
            return next(new InternalServerError('could not construct url'));
        }

        redirectLocation = url.format(finalUri);

        self.emit('redirect', redirectLocation);

        // now we're done constructing url, send the res
        self.send(statusCode, null, {
            Location: redirectLocation
        });

        // tell server to stop processing the handler stack.
        return next(false);
    }
@private
@param {*} arg1 - arg1
@param {*} arg2 - arg2
@param {*} arg3 - arg3
@fires    redirect
@function redirect
@returns  {undefined} no return value