You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

file.js 1.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /**
  2. * Module dependencies.
  3. */
  4. var fs = require('fs');
  5. var uri2path = require('file-uri-to-path');
  6. var NotFoundError = require('./notfound');
  7. var NotModifiedError = require('./notmodified');
  8. var debug = require('debug')('get-uri:file');
  9. /**
  10. * Module exports.
  11. */
  12. module.exports = get;
  13. /**
  14. * Returns a `fs.ReadStream` instance from a "file:" URI.
  15. *
  16. * @api protected
  17. */
  18. function get (parsed, opts, fn) {
  19. var fd;
  20. var cache = opts.cache;
  21. // same as in fs.ReadStream's constructor
  22. var flags = opts.hasOwnProperty('flags') ? options.flags : 'r';
  23. var mode = opts.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/
  24. // convert URI → Path
  25. var uri = parsed.href;
  26. var filepath = uri2path(uri);
  27. debug('normalized pathname: %o', filepath);
  28. // open() first to get a fd and ensure that the file exists
  29. fs.open(filepath, flags, mode, onopen);
  30. function onerror (err) {
  31. if ('number' == typeof fd) {
  32. fs.close(fd, onclose);
  33. }
  34. fn(err);
  35. }
  36. function onclose () {
  37. debug('closed fd %o', fd);
  38. }
  39. function onopen (err, _fd) {
  40. if (err) {
  41. if ('ENOENT' == err.code) {
  42. err = new NotFoundError();
  43. }
  44. return onerror(err);
  45. }
  46. fd = _fd;
  47. // now fstat() to check the `mtime` and store the stat object for the cache
  48. fs.fstat(fd, onstat);
  49. }
  50. function onstat (err, stat) {
  51. if (err) return onerror(err);
  52. // if a `cache` was provided, check if the file has not been modified
  53. if (cache && cache.stat && stat && isNotModified(cache.stat, stat)) {
  54. return onerror(new NotModifiedError());
  55. }
  56. // `fs.ReadStream` takes care of calling `fs.close()` on the
  57. // fd after it's done reading
  58. opts.fd = fd;
  59. var rs = fs.createReadStream(null, opts);
  60. rs.stat = stat;
  61. fn(null, rs);
  62. }
  63. // returns `true` if the `mtime` of the 2 stat objects are equal
  64. function isNotModified (prev, curr) {
  65. return +prev.mtime == +curr.mtime;
  66. }
  67. }