Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

inert

Package Overview
Dependencies
Maintainers
2
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

inert - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

test/directory/index.js

42

lib/directory.js

@@ -19,3 +19,3 @@ // Load modules

path: Joi.alternatives(Joi.array().includes(Joi.string()).single(), Joi.func()).required(),
index: Joi.boolean(),
index: Joi.alternatives(Joi.boolean(), Joi.array().includes(Joi.string()).single()).default(true),
listing: Joi.boolean(),

@@ -54,2 +54,4 @@ showHidden: Joi.boolean(),

var indexNames = (settings.index === true) ? ['index.html'] : (settings.index || []);
// Declare handler

@@ -137,4 +139,3 @@

var index = (settings.index !== false); // Defaults to true
if (!index &&
if (indexNames.length === 0 &&
!settings.listing) {

@@ -152,24 +153,29 @@

if (!index) {
return internals.generateListing(path, resource, selection, hasTrailingSlash, settings, request, reply);
}
Items.serial(indexNames, function (indexName, next) {
var indexFile = Path.join(path, 'index.html');
File.load(indexFile, request, { lookupCompressed: settings.lookupCompressed }, function (indexResponse) {
var indexFile = Path.join(path, indexName);
File.load(indexFile, request, { lookupCompressed: settings.lookupCompressed }, function (indexResponse) {
// File loaded successfully
// File loaded successfully
if (!indexResponse.isBoom) {
return reply(indexResponse);
}
if (!indexResponse.isBoom) {
return reply(indexResponse);
}
// Directory
// Directory
var err = indexResponse;
if (err.output.statusCode !== 404) {
return reply(Boom.badImplementation('index.html is a directory'));
}
var err = indexResponse;
if (err.output.statusCode !== 404) {
return reply(Boom.badImplementation(indexName + ' is a directory'));
}
// Not found
// Not found, try the next one
return next();
});
},
function (/* err */) {
// None of the index files were found
if (!settings.listing) {

@@ -176,0 +182,0 @@ return reply(Boom.forbidden());

@@ -6,2 +6,3 @@ // Load modules

var Crypto = require('crypto');
var Ammo = require('ammo');
var Boom = require('boom');

@@ -133,3 +134,3 @@ var Hoek = require('hoek');

return next(null, internals.openStream(response, response.source.path));
return internals.openStream(response, response.source.path, next);
}

@@ -141,3 +142,3 @@

if (err) {
return next(null, internals.openStream(response, response.source.path));
return internals.openStream(response, response.source.path, next);
}

@@ -152,3 +153,3 @@

return next(null, internals.openStream(response, gzFile));
return internals.openStream(response, gzFile, next);
});

@@ -158,9 +159,47 @@ };

internals.openStream = function (response, path) {
internals.openStream = function (response, path, next) {
Hoek.assert(response.source.fd !== null, 'file descriptor must be set');
var fileStream = Fs.createReadStream(path, { fd: response.source.fd });
// Check for Range request
var request = response.request;
var length = response.headers['content-length'];
var options = { fd: response.source.fd };
if (request.headers.range && length) {
// Check If-Range
if (!request.headers['if-range'] ||
request.headers['if-range'] === response.headers.etag) { // Ignoring last-modified date (weak)
// Parse header
var ranges = Ammo.header(request.headers.range, length);
if (!ranges) {
var error = Boom.rangeNotSatisfiable();
error.output.headers['content-range'] = 'bytes */' + length;
return next(error);
}
// Prepare transform
if (ranges.length === 1) { // Ignore requests for multiple ranges
var range = ranges[0];
response.code(206);
response.bytes(range.to - range.from + 1);
response._header('content-range', 'bytes ' + range.from + '-' + range.to + '/' + length);
options.start = range.from;
options.end = range.to;
}
}
}
response._header('accept-ranges', 'bytes');
var fileStream = Fs.createReadStream(path, options);
response.source.fd = null; // Claim descriptor
return fileStream;
return next(null, fileStream);
};

@@ -167,0 +206,0 @@

{
"name": "inert",
"description": "Static file and directory handlers plugin for hapi.js",
"version": "2.0.0",
"version": "2.1.0",
"repository": "git://github.com/hapijs/inert",

@@ -18,2 +18,3 @@ "main": "index",

"dependencies": {
"ammo": "1.x.x",
"boom": "2.x.x",

@@ -31,3 +32,4 @@ "hoek": "2.x.x",

"scripts": {
"test": "make test-cov"
"test": "lab -a code -t 100 -L",
"test-cov-html": "lab -a code -r html -o coverage.html"
},

@@ -34,0 +36,0 @@ "licenses": [

@@ -268,3 +268,3 @@ // Load modules

it('returns the index when found', function (done) {
it('returns the "index.html" index file when found and default index enabled', function (done) {

@@ -282,2 +282,52 @@ var server = provisionServer();

it('returns the index file when found and single custom index file specified', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: 'index.js' } } });
server.inject('/directoryIndex/', function (res) {
expect(res.statusCode).to.equal(200);
expect(res.payload).to.contain('var isTest = true;');
done();
});
});
it('returns the first index file found when an array of index files is specified', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: ['default.html', 'index.js', 'non.existing'] } } });
server.inject('/directoryIndex/', function (res) {
expect(res.statusCode).to.equal(200);
expect(res.payload).to.contain('var isTest = true;');
done();
});
});
it('returns a 403 when listing is disabled and a custom index file is specified but not found', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: 'default.html' } } });
server.inject('/directoryIndex/', function (res) {
expect(res.statusCode).to.equal(403);
done();
});
});
it('returns a 403 when listing is disabled and an array of index files is specified but none were found', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: ['default.html', 'non.existing'] } } });
server.inject('/directoryIndex/', function (res) {
expect(res.statusCode).to.equal(403);
done();
});
});
it('returns the index when served from a hidden folder', function (done) {

@@ -327,2 +377,14 @@

it('returns a 500 when the custom index is a directory', function (done) {
var server = provisionServer(null, false);
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: 'misc' } } });
server.inject('/directoryIndex/invalid/', function (res) {
expect(res.statusCode).to.equal(500);
done();
});
});
it('returns the correct file when using a fn directory handler', function (done) {

@@ -329,0 +391,0 @@

@@ -939,2 +939,200 @@ // Load modules

describe('response range', function () {
it('returns a subset of a file (start)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=0-4' } }, function (res) {
expect(res.statusCode).to.equal(206);
expect(res.headers['content-length']).to.equal(5);
expect(res.headers['content-range']).to.equal('bytes 0-4/42010');
expect(res.headers['accept-ranges']).to.equal('bytes');
expect(res.payload).to.equal('\x89PNG\r');
done();
});
});
it('returns a subset of a file (middle)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=1-5' } }, function (res) {
expect(res.statusCode).to.equal(206);
expect(res.headers['content-length']).to.equal(5);
expect(res.headers['content-range']).to.equal('bytes 1-5/42010');
expect(res.headers['accept-ranges']).to.equal('bytes');
expect(res.payload).to.equal('PNG\r\n');
done();
});
});
it('returns a subset of a file (-to)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=-5' } }, function (res) {
expect(res.statusCode).to.equal(206);
expect(res.headers['content-length']).to.equal(5);
expect(res.headers['content-range']).to.equal('bytes 42005-42009/42010');
expect(res.headers['accept-ranges']).to.equal('bytes');
expect(res.payload).to.equal('D\xAEB\x60\x82');
done();
});
});
it('returns a subset of a file (from-)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=42005-' } }, function (res) {
expect(res.statusCode).to.equal(206);
expect(res.headers['content-length']).to.equal(5);
expect(res.headers['content-range']).to.equal('bytes 42005-42009/42010');
expect(res.headers['accept-ranges']).to.equal('bytes');
expect(res.payload).to.equal('D\xAEB\x60\x82');
done();
});
});
it('returns a subset of a file (beyond end)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=42005-42011' } }, function (res) {
expect(res.statusCode).to.equal(206);
expect(res.headers['content-length']).to.equal(5);
expect(res.headers['content-range']).to.equal('bytes 42005-42009/42010');
expect(res.headers['accept-ranges']).to.equal('bytes');
expect(res.payload).to.equal('D\xAEB\x60\x82');
done();
});
});
it('returns a subset of a file (if-range)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject('/file', function (res) {
server.inject('/file', function (res1) {
server.inject({ url: '/file', headers: { 'range': 'bytes=42005-42011', 'if-range': res1.headers.etag } }, function (res2) {
expect(res2.statusCode).to.equal(206);
expect(res2.headers['content-length']).to.equal(5);
expect(res2.headers['content-range']).to.equal('bytes 42005-42009/42010');
expect(res2.headers['accept-ranges']).to.equal('bytes');
expect(res2.payload).to.equal('D\xAEB\x60\x82');
done();
});
});
});
});
it('returns 200 on incorrect if-range', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=42005-42011', 'if-range': 'abc' } }, function (res2) {
expect(res2.statusCode).to.equal(200);
done();
});
});
it('returns 416 on invalid range (unit)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'horses=1-5' } }, function (res) {
expect(res.statusCode).to.equal(416);
expect(res.headers['content-range']).to.equal('bytes */42010');
done();
});
});
it('returns 416 on invalid range (inversed)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=5-1' } }, function (res) {
expect(res.statusCode).to.equal(416);
expect(res.headers['content-range']).to.equal('bytes */42010');
done();
});
});
it('returns 416 on invalid range (format)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes 1-5' } }, function (res) {
expect(res.statusCode).to.equal(416);
expect(res.headers['content-range']).to.equal('bytes */42010');
done();
});
});
it('returns 416 on invalid range (empty range)', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=-' } }, function (res) {
expect(res.statusCode).to.equal(416);
expect(res.headers['content-range']).to.equal('bytes */42010');
done();
});
});
it('returns 200 on multiple ranges', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png') } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=1-5,7-10' } }, function (res) {
expect(res.statusCode).to.equal(200);
expect(res.headers['content-length']).to.equal(42010);
done();
});
});
it('returns a subset of a file using precompressed file', function (done) {
var server = provisionServer();
server.route({ method: 'GET', path: '/file', handler: { file: { path: Path.join(__dirname, 'file/image.png'), lookupCompressed: true } } });
server.inject({ url: '/file', headers: { 'range': 'bytes=10-18', 'accept-encoding': 'gzip' } }, function (res) {
expect(res.statusCode).to.equal(206);
expect(res.headers['content-encoding']).to.equal('gzip');
expect(res.headers['content-length']).to.equal(9);
expect(res.headers['content-range']).to.equal('bytes 10-18/41936');
expect(res.headers['accept-ranges']).to.equal('bytes');
expect(res.payload).to.equal('image.png');
done();
});
});
});
it('has not leaked file descriptors', { skip: process.platform === 'win32' }, function (done) {

@@ -941,0 +1139,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc