function serveStatic(options) {
    var opts = options || {};

    if (typeof opts.appendRequestPath === 'undefined') {
        opts.appendRequestPath = true;
    }

    assert.object(opts, 'options');
    assert.string(opts.directory, 'options.directory');
    assert.optionalNumber(opts.maxAge, 'options.maxAge');
    assert.optionalObject(opts.match, 'options.match');
    assert.optionalString(opts.charSet, 'options.charSet');
    assert.optionalString(opts.file, 'options.file');
    assert.bool(opts.appendRequestPath, 'options.appendRequestPath');

    var p = path.normalize(opts.directory).replace(/\\/g, '/');
    var re = new RegExp('^' + escapeRE(p) + '/?.*');

    function serveFileFromStats(file, err, stats, isGzip, req, res, next) {
        if (
            typeof req.connectionState === 'function' &&
            req.connectionState() === 'close'
        ) {
            next(false);
            return;
        }

        if (err) {
            next(new ResourceNotFoundError(err, '%s', req.path()));
            return;
        } else if (!stats.isFile()) {
            next(new ResourceNotFoundError('%s does not exist', req.path()));
            return;
        }

        if (res.handledGzip && isGzip) {
            res.handledGzip();
        }

        var fstream = fs.createReadStream(file + (isGzip ? '.gz' : ''));
        var maxAge = opts.maxAge === undefined ? 3600 : opts.maxAge;
        fstream.once('open', function onceOpen(fd) {
            res.cache({ maxAge: maxAge });
            res.set('Content-Length', stats.size);
            res.set('Content-Type', mime.getType(file));
            res.set('Last-Modified', stats.mtime);

            if (opts.charSet) {
                var type =
                    res.getHeader('Content-Type') + '; charset=' + opts.charSet;
                res.setHeader('Content-Type', type);
            }

            if (opts.etag) {
                res.set('ETag', opts.etag(stats, opts));
            }
            res.writeHead(200);
            fstream.pipe(res);
            fstream.once('close', function onceClose() {
                next(false);
            });
        });

        res.once('close', function onceClose() {
            fstream.close();
        });
    }

    function serveNormal(file, req, res, next) {
        fs.stat(file, function fileStat(err, stats) {
            if (!err && stats.isDirectory() && opts.default) {
                // Serve an index.html page or similar
                var filePath = path.join(file, opts.default);
                fs.stat(filePath, function dirStat(dirErr, dirStats) {
                    serveFileFromStats(
                        filePath,
                        dirErr,
                        dirStats,
                        false,
                        req,
                        res,
                        next
                    );
                });
            } else {
                serveFileFromStats(file, err, stats, false, req, res, next);
            }
        });
    }

    function serve(req, res, next) {
        var file;

        if (opts.file) {
            //serves a direct file
            file = path.join(opts.directory, decodeURIComponent(opts.file));
        } else if (opts.appendRequestPath) {
            file = path.join(opts.directory, decodeURIComponent(req.path()));
        } else {
            var dirBasename = path.basename(opts.directory);
            var reqpathBasename = path.basename(req.path());

            if (
                path.extname(req.path()) === '' &&
                dirBasename === reqpathBasename
            ) {
                file = opts.directory;
            } else {
                file = path.join(
                    opts.directory,
                    decodeURIComponent(path.basename(req.path()))
                );
            }
        }

        if (req.method !== 'GET' && req.method !== 'HEAD') {
            next(new MethodNotAllowedError('%s', req.method));
            return;
        }

        if (!re.test(file.replace(/\\/g, '/'))) {
            next(new NotAuthorizedError('%s', req.path()));
            return;
        }

        if (opts.match && !opts.match.test(file)) {
            next(new NotAuthorizedError('%s', req.path()));
            return;
        }

        if (opts.gzip && req.acceptsEncoding('gzip')) {
            fs.stat(file + '.gz', function stat(err, stats) {
                if (!err) {
                    res.setHeader('Content-Encoding', 'gzip');
                    serveFileFromStats(file, err, stats, true, req, res, next);
                } else {
                    serveNormal(file, req, res, next);
                }
            });
        } else {
            serveNormal(file, req, res, next);
        }
    }

    return serve;
}
Serves static files.

@public
@function serveStatic
@param    {Object} options - an options object
@throws   {MethodNotAllowedError} |
@throws   {NotAuthorizedError}
@throws   {ResourceNotFoundError}
@returns  {Function} Handler
@example
<caption>
The serveStatic module is different than most of the other plugins, in that
it is expected that you are going to map it to a route, as below:
</caption>
server.get('/docs/current/*', restify.plugins.serveStatic({
  directory: './documentation/v1',
  default: 'index.html'
}));
@example
<caption>
The above `route` and `directory` combination will serve a file located in
`./documentation/v1/docs/current/index.html` when you attempt to hit
`http://localhost:8080/docs/current/`. If you want the serveStatic module to
serve files directly from the `/documentation/v1` directory
(and not append the request path `/docs/current/`),
you can set the `appendRequestPath` option to `false`, and the served file
would be `./documentation/v1/index.html`, in the previous example.

The plugin will enforce that all files under `directory` are served.
The `directory` served is relative to the process working directory.
You can also provide a `default` parameter such as index.html for any
directory that lacks a direct file match.
You can specify additional restrictions by passing in a `match` parameter,
which is just a `RegExp` to check against the requested file name.
Additionally, you may set the `charSet` parameter, which will append a
character set to the content-type detected by the plugin.
For example, `charSet: 'utf-8'` will result in HTML being served with a
`Content-Type` of `text/html; charset=utf-8`.
Lastly, you can pass in a `maxAge` numeric, which will set the
`Cache-Control` header. Default is `3600` (1 hour).

An additional option for serving a static file is to pass `file` in to the
serveStatic method as an option. The following will serve index.html from
the documentation/v1/ directory anytime a client requests `/home/`.
</caption>
server.get('/home/*', restify.plugins.serveStatic({
  directory: './documentation/v1',
  file: 'index.html'
}));
// or
server.get('/home/([a-z]+[.]html)', restify.plugins.serveStatic({
  directory: './documentation/v1',
  file: 'index.html'
}));