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

combohandler

Package Overview
Dependencies
Maintainers
2
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

combohandler - npm Package Compare versions

Comparing version 0.3.6 to 0.3.7

test/fixtures/dynamic/baddecaf/baddecaf/e.js

13

HISTORY.md
Combo Handler History
=====================
0.3.7 (2013-10-22)
------------------
* Fixed a few `dynamicPath` middleware edge cases with multiple and duplicate
route parameters.
* Added --no-resolve-symlinks option that uses fs.statSync to validate rootPath
instead of fs.realpathSync. Caveat emptor.
* Updated jshint devDependency to 2.3.0.
* Updated should devDependency to 2.0.2.
0.3.6 (2013-10-18)

@@ -5,0 +18,0 @@ ------------------

@@ -17,2 +17,3 @@ /**

"restart": Boolean,
"resolveSymlinks": Boolean,
"root": [String, Array],

@@ -30,2 +31,3 @@ "rootsFile": path,

var shortHands = {
"--no-resolve-symlinks": ["--no-resolveSymlinks"],
"h": ["--help"],

@@ -71,2 +73,5 @@ "v": ["--version"],

msg.push("");
msg.push(" --no-resolve-symlinks");
msg.push(" If passed, rootPaths that are symlinks will not be resolved (the default).");
msg.push("");
msg.push("Cluster Options:");

@@ -73,0 +78,0 @@ msg.push(" --cluster Enable clustering of server across multiple processes.");

2

lib/combohandler.js

@@ -47,3 +47,3 @@ var fs = require('fs'),

// error.
rootPathResolved = resolvePathSync(config.rootPath);
rootPathResolved = resolvePathSync(config.rootPath, config.resolveSymlinks);
}

@@ -50,0 +50,0 @@

@@ -46,3 +46,3 @@ /**

// cache config object used in middleware
dynamicPathMiddleware.CONFIG = parseConfig(options.rootPath);
dynamicPathMiddleware.CONFIG = parseConfig(options.rootPath, options.resolveSymlinks);

@@ -59,8 +59,8 @@ return dynamicPathMiddleware;

dynamicParams.forEach(function (dynamicParam) {
dynamicParams.forEach(function (dynamicParam, idx) {
var dynamicValue = dynamicParam && params[dynamicParam];
if (dynamicValue) {
// rootSuffixes contribute to cache key
if (rootSuffixes[dynamicParam]) {
dynamicValue = path.join(dynamicValue, rootSuffixes[dynamicParam]);
if (rootSuffixes[idx]) {
dynamicValue = path.join(dynamicValue, rootSuffixes[idx]);
}

@@ -107,3 +107,4 @@

@method parseConfig
@param {String} rootPatha
@param {String} rootPath
@param {Boolean} resolveSymlinks
@return {Object} config

@@ -116,3 +117,3 @@ @property {String} config.rootPath

**/
function parseConfig(rootPath) {
function parseConfig(rootPath, resolveSymlinks) {
rootPath = path.normalize(rootPath);

@@ -122,3 +123,3 @@

var dynamicParams = [];
var rootSuffixes = {};
var rootSuffixes = [];

@@ -139,7 +140,10 @@ // str.match() in route config returns null if no matches or [":foo"]

// rootSuffixes must be stored for use in getDynamicRoot
rootSuffixes[keyName] = rootPath.substr(rootPath.indexOf(dynamicKey) + dynamicKey.length);
rootSuffixes.unshift(rootPath.split(dynamicKey).pop());
} else {
// maintain correct indices with non-matching keys
rootSuffixes.unshift('');
}
// remove key + suffix from rootPath used in initial realpathSync
rootPath = rootPath.substring(0, rootPath.indexOf(dynamicKey));
// remove key + suffix from rootPath used in initial resolvePathSync
rootPath = rootPath.substring(0, rootPath.lastIndexOf(dynamicKey));
});

@@ -150,3 +154,3 @@ }

// middleware is initialized, and we want it to throw if there's an error.
rootPath = resolvePathSync(rootPath);
rootPath = resolvePathSync(rootPath, resolveSymlinks);

@@ -153,0 +157,0 @@ return {

@@ -46,7 +46,16 @@ /**

function resolvePathSync(rootPath) {
function resolvePathSync(rootPath, resolveSymlinks) {
// Turns out fs.realpathSync always defaults empty strings to cwd().
rootPath = rootPath || process.cwd();
// Intentionally using the sync method because this only runs when the
// middleware is initialized, and we want it to throw if there's an error.
if (resolveSymlinks !== false) {
rootPath = fs.realpathSync(rootPath);
} else {
fs.statSync(rootPath);
}
// The resulting rootPath should always have a trailing slash.
return path.normalize(fs.realpathSync(rootPath || '') + path.sep);
return path.normalize(rootPath + path.sep);
}
{
"name" : "combohandler",
"description": "Simple Yahoo!-style combo handler.",
"version" : "0.3.6",
"version" : "0.3.7",
"keywords" : [

@@ -47,7 +47,7 @@ "combo", "combohandler", "combohandle", "combine", "cdn", "css", "yui"

"istanbul": "0.1.44",
"jshint" : "2.1.11",
"jshint" : "2.3.0",
"mocha" : "1.13.0",
"request" : "2.27.0",
"rimraf" : "2.2.2",
"should" : "2.0.1",
"should" : "2.0.2",
"sinon" : "1.7.3"

@@ -54,0 +54,0 @@ },

@@ -590,5 +590,17 @@ /*global describe, before, after, it, sinon */

app.get("/:major/separated/by/:minor",
app.get("/:major/separated/route/:minor",
combo.combine({ rootPath: FIXTURES_DIR + "/:major/:minor/static" }),
combo.respond);
app.get("/:major/separated/path/:minor",
combo.combine({ rootPath: FIXTURES_DIR + "/:major/decafbad/:minor" }),
combo.respond);
app.get('/doubled-in-rootpath/:major',
combo.combine({ rootPath: FIXTURES_DIR + '/dynamic/:major/:major' }),
combo.respond);
app.get('/doubled-with-suffixes/:major',
combo.combine({ rootPath: FIXTURES_DIR + '/dynamic/:major/static/:major' }),
combo.respond);
});

@@ -612,5 +624,20 @@

it("should resolve route that has separated parameters", assertResponds({
path: "/dynamic/separated/by/decafbad?c.js&d.js",
path: "/dynamic/separated/route/decafbad?c.js&d.js",
body: "c();\n\nd();\n"
}));
it("should resolve root path that has separated parameters", assertResponds({
path: "/dynamic/separated/path/static?c.js&d.js",
body: "c();\n\nd();\n"
}));
it("should resolve route that has identical parameters in root path", assertResponds({
path: "/doubled-in-rootpath/baddecaf?e.js&f.js",
body: "e();\n\nf();\n"
}));
it("should resolve route that has separated identical parameters in root path", assertResponds({
path: "/doubled-with-suffixes/cafebabe?g.js&h.js",
body: "g();\n\nh();\n"
}));
});

@@ -652,2 +679,38 @@ });

function dynamicFiletree(opts) {
var expectedRelativePath = opts.relativePath || "js/a.js";
var expectedResolvedPath = path.join(COMPLEX_ROOT, opts.realPath, expectedRelativePath);
var expectedRootPath = path.join(COMPLEX_ROOT, opts.rootPath);
return function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(expectedRootPath);
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal(expectedRelativePath);
fs.realpath(path.join(rootPath, relativePath), function (err, resolved) {
assert.ifError(err);
resolved.should.equal(expectedResolvedPath);
next();
});
};
}
function dynamicSymlinks(opts) {
var expectedTemplateFile = opts.template || TEMPLATE_SIMPLE;
var expectedRelativePath = opts.relativePath || "css/urls/simple.css";
var expectedResolvedBody = expectedTemplateFile.replace(/__ROOT__/g, opts.rootPath);
return function (req, res, next) {
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal(expectedRelativePath);
// console.error(res.body);
res.body.should.equal(expectedResolvedBody);
next();
};
}
describe("route with fully-qualified dynamic path", function () {

@@ -660,36 +723,17 @@ before(function () {

app.get("/c/:version/fs-fq", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/versioned/deeper/base/'));
next();
}, combo.respond);
app.get("/c/:version/fs-fq", combined, dynamicFiletree({
realPath: "/versioned/deeper/base/",
rootPath: "/versioned/deeper/base/"
}), combo.respond);
app.get("/c/:version/ln-fq", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/versioned/shallower/base/'));
app.get("/c/:version/ln-fq", combined, dynamicFiletree({
realPath: "/base/",
rootPath: "/versioned/shallower/base/"
}), combo.respond);
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal('js/a.js');
fs.realpath(path.join(rootPath, relativePath), function (err, resolved) {
assert.ifError(err);
resolved.should.equal(path.join(COMPLEX_ROOT, '/base/', relativePath));
next();
});
}, combo.respond);
app.get("/c/:version/fq-noimports", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/versioned/shallower/base/'));
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal('css/urls/simple.css');
// console.error(res.body);
var expected = (SIMPLE_IMPORTS_RAW + TEMPLATE_URLS_SIMPLE)
.replace(/__ROOT__/g, '/versioned/shallower/base/');
res.body.should.equal(expected);
next();
}, combo.respond);
app.get("/c/:version/fq-noimports", combined, dynamicSymlinks({
template: SIMPLE_IMPORTS_RAW + TEMPLATE_URLS_SIMPLE,
realPath: "/versioned/shallower/base/",
rootPath: "/versioned/shallower/base/"
}), combo.respond);
});

@@ -712,87 +756,113 @@

describe("and rootPath symlinked shallower", function () {
before(function () {
var combined = combo.combine({
rewriteImports: true,
webRoot : COMPLEX_ROOT,
rootPath: COMPLEX_ROOT + '/versioned/shallower/base/'
describe("when resolveSymlinks is true", function () {
before(function () {
var resolved = combo.combine({
rewriteImports: true,
webRoot : COMPLEX_ROOT,
rootPath: COMPLEX_ROOT + '/versioned/shallower/base/'
});
app.get("/r/:version/fs-shallow", resolved, dynamicFiletree({
realPath: "/base/",
rootPath: "/base/"
}), combo.respond);
app.get("/r/:version/ln-shallow", resolved, dynamicSymlinks({
rootPath: "/base/"
}), combo.respond);
});
app.get("/c/:version/fs-shallow", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/base/'));
it("should resolve files from realpath in filesystem", assertResponds({
path: "/r/cafebabe/fs-shallow?js/a.js&js/b.js"
}));
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal('js/a.js');
it("should rewrite url() through symlink", assertResponds({
path: "/r/cafebabe/ln-shallow?css/urls/simple.css"
}));
});
fs.realpath(path.join(rootPath, relativePath), function (err, resolved) {
assert.ifError(err);
resolved.should.equal(path.join(COMPLEX_ROOT, '/base/', relativePath));
next();
describe("when resolveSymlinks is false", function () {
before(function () {
var symlinkd = combo.combine({
rewriteImports: true,
resolveSymlinks: false,
webRoot : COMPLEX_ROOT,
rootPath: COMPLEX_ROOT + '/versioned/shallower/base/'
});
}, combo.respond);
app.get("/c/:version/ln-shallow", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/base/'));
app.get("/s/:version/fs-shallow", symlinkd, dynamicFiletree({
realPath: "/base/",
rootPath: "/versioned/shallower/base/"
}), combo.respond);
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal('css/urls/simple.css');
app.get("/s/:version/ln-shallow", symlinkd, dynamicSymlinks({
rootPath: "/versioned/shallower/base/"
}), combo.respond);
});
// console.error(res.body);
res.body.should.equal(TEMPLATE_SIMPLE.replace(/__ROOT__/g, '/base/'));
it("should resolve files from symlink in filesystem", assertResponds({
path: "/s/cafebabe/fs-shallow?js/a.js&js/b.js"
}));
next();
}, combo.respond);
it("should rewrite url() using symlink", assertResponds({
path: "/s/cafebabe/ln-shallow?css/urls/simple.css"
}));
});
});
it("should resolve files from realpath in filesystem", assertResponds({
path: "/c/cafebabe/fs-shallow?js/a.js&js/b.js"
}));
describe("and rootPath symlinked deeper", function () {
describe("when resolveSymlinks is true", function () {
before(function () {
var resolved = combo.combine({
rewriteImports: true,
webRoot : COMPLEX_ROOT,
rootPath: COMPLEX_ROOT + '/deep-link/'
});
it("should rewrite url() through symlink", assertResponds({
path: "/c/cafebabe/ln-shallow?css/urls/simple.css"
}));
});
app.get("/r/:version/fs-deeper", resolved, dynamicFiletree({
realPath: "/versioned/deeper/base/",
rootPath: "/versioned/deeper/base/"
}), combo.respond);
describe("and rootPath symlinked deeper", function () {
before(function () {
var combined = combo.combine({
rewriteImports: true,
webRoot : COMPLEX_ROOT,
rootPath: COMPLEX_ROOT + '/deep-link/'
app.get("/r/:version/ln-deeper", resolved, dynamicSymlinks({
rootPath: "/versioned/deeper/base/"
}), combo.respond);
});
app.get("/c/:version/fs-deeper", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/versioned/deeper/base/'));
it("should read rootPath from filesystem directly", assertResponds({
path: "/r/cafebabe/fs-deeper?js/a.js&js/b.js"
}));
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal('js/a.js');
it("should *still* rewrite url() through symlink", assertResponds({
path: "/r/cafebabe/ln-deeper?css/urls/simple.css"
}));
});
next();
}, combo.respond);
describe("when resolveSymlinks is false", function () {
before(function () {
var symlinkd = combo.combine({
rewriteImports: true,
resolveSymlinks: false,
webRoot : COMPLEX_ROOT,
rootPath: COMPLEX_ROOT + '/deep-link/'
});
app.get("/c/:version/ln-deeper", combined, function (req, res, next) {
var rootPath = res.locals.rootPath;
rootPath.should.equal(path.join(COMPLEX_ROOT, '/versioned/deeper/base/'));
app.get("/s/:version/fs-deeper", symlinkd, dynamicFiletree({
realPath: "/versioned/deeper/base/",
rootPath: "/deep-link/"
}), combo.respond);
var relativePath = res.locals.relativePaths[0];
relativePath.should.equal('css/urls/simple.css');
app.get("/s/:version/ln-deeper", symlinkd, dynamicSymlinks({
rootPath: "/deep-link/"
}), combo.respond);
});
// console.error(res.body);
var expected = TEMPLATE_SIMPLE
.replace(/__ROOT__/g, '/versioned/deeper/base/');
res.body.should.equal(expected);
it("should read rootPath from symlink in filesystem", assertResponds({
path: "/s/cafebabe/fs-deeper?js/a.js&js/b.js"
}));
next();
}, combo.respond);
it("should *still* rewrite url() using symlink", assertResponds({
path: "/s/cafebabe/ln-deeper?css/urls/simple.css"
}));
});
it("should read rootPath from filesystem directly", assertResponds({
path: "/c/cafebabe/fs-deeper?js/a.js&js/b.js"
}));
it("should *still* rewrite url() through symlink", assertResponds({
path: "/c/cafebabe/ln-deeper?css/urls/simple.css"
}));
});

@@ -799,0 +869,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