87 lines
1.9 KiB
JavaScript
87 lines
1.9 KiB
JavaScript
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
|
|
var fs = require('fs');
|
|
var uri2path = require('file-uri-to-path');
|
|
var NotFoundError = require('./notfound');
|
|
var NotModifiedError = require('./notmodified');
|
|
var debug = require('debug')('get-uri:file');
|
|
|
|
/**
|
|
* Module exports.
|
|
*/
|
|
|
|
module.exports = get;
|
|
|
|
/**
|
|
* Returns a `fs.ReadStream` instance from a "file:" URI.
|
|
*
|
|
* @api protected
|
|
*/
|
|
|
|
function get (parsed, opts, fn) {
|
|
|
|
var fd;
|
|
var cache = opts.cache;
|
|
|
|
// same as in fs.ReadStream's constructor
|
|
var flags = opts.hasOwnProperty('flags') ? options.flags : 'r';
|
|
var mode = opts.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/
|
|
|
|
// convert URI → Path
|
|
var uri = parsed.href;
|
|
var filepath = uri2path(uri);
|
|
debug('normalized pathname: %o', filepath);
|
|
|
|
// open() first to get a fd and ensure that the file exists
|
|
fs.open(filepath, flags, mode, onopen);
|
|
|
|
function onerror (err) {
|
|
if ('number' == typeof fd) {
|
|
fs.close(fd, onclose);
|
|
}
|
|
fn(err);
|
|
}
|
|
|
|
function onclose () {
|
|
debug('closed fd %o', fd);
|
|
}
|
|
|
|
function onopen (err, _fd) {
|
|
if (err) {
|
|
if ('ENOENT' == err.code) {
|
|
err = new NotFoundError();
|
|
}
|
|
return onerror(err);
|
|
}
|
|
fd = _fd;
|
|
|
|
// now fstat() to check the `mtime` and store the stat object for the cache
|
|
fs.fstat(fd, onstat);
|
|
}
|
|
|
|
function onstat (err, stat) {
|
|
if (err) return onerror(err);
|
|
|
|
// if a `cache` was provided, check if the file has not been modified
|
|
if (cache && cache.stat && stat && isNotModified(cache.stat, stat)) {
|
|
return onerror(new NotModifiedError());
|
|
}
|
|
|
|
// `fs.ReadStream` takes care of calling `fs.close()` on the
|
|
// fd after it's done reading
|
|
opts.fd = fd;
|
|
var rs = fs.createReadStream(null, opts);
|
|
rs.stat = stat;
|
|
|
|
fn(null, rs);
|
|
}
|
|
|
|
// returns `true` if the `mtime` of the 2 stat objects are equal
|
|
function isNotModified (prev, curr) {
|
|
return +prev.mtime == +curr.mtime;
|
|
}
|
|
}
|