-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Anthony Frasso
committed
Aug 12, 2016
1 parent
72fed3b
commit fa28369
Showing
6 changed files
with
263 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{ | ||
"disallowEmptyBlocks": true, | ||
"disallowFunctionDeclarations": true, | ||
"disallowImplicitTypeConversion": ["numeric", "boolean", "binary", "string"], | ||
"disallowKeywordsOnNewLine": [ "else" ], | ||
"disallowMixedSpacesAndTabs": true, | ||
"disallowMultipleLineBreaks": true, | ||
"disallowNewlineBeforeBlockStatements": true, | ||
"disallowPaddingNewlinesInBlocks": true, | ||
"disallowQuotedKeysInObjects": true, | ||
"disallowSpaceAfterObjectKeys": true, | ||
"disallowSpaceAfterPrefixUnaryOperators": [ "++", "--", "+", "-", "~", "!" ], | ||
"disallowSpaceBeforeComma": true, | ||
"disallowSpaceBeforePostfixUnaryOperators": [ "++", "--" ], | ||
"disallowSpaceBeforeSemicolon": true, | ||
"disallowSpacesInAnonymousFunctionExpression": { | ||
"beforeOpeningRoundBrace": true | ||
}, | ||
"disallowSpacesInCallExpression": true, | ||
"disallowSpacesInsideParentheses": true, | ||
"disallowTabs": true, | ||
"disallowTrailingComma": true, | ||
"disallowTrailingWhitespace": true, | ||
"maximumLineLength": 120, | ||
"requireBlocksOnNewline": true, | ||
"requireCamelCaseOrUpperCaseIdentifiers": true, | ||
"requireCapitalizedConstructorsNew": true, | ||
"requireCapitalizedConstructors": true, | ||
"requireCommaBeforeLineBreak": true, | ||
"requireCurlyBraces": [ "if", "else", "for", "while", "do", "try", "catch" ], | ||
"requireDotNotation": true, | ||
"requireImportAlphabetized": true, | ||
"requireLineBreakAfterVariableAssignment": true, | ||
"requireLineFeedAtFileEnd": true, | ||
"requireMatchingFunctionName": true, | ||
"requireOperatorBeforeLineBreak": true, | ||
"requireSemicolons": true, | ||
"requireSpaceAfterBinaryOperators": true, | ||
"requireSpaceAfterComma": true, | ||
"requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "try", "catch" ], | ||
"requireSpaceAfterLineComment": true, | ||
"requireSpaceBeforeBinaryOperators": true, | ||
"requireSpaceBeforeBlockStatements": true, | ||
"requireSpaceBetweenArguments": true, | ||
"requireSpacesInAnonymousFunctionExpression": { | ||
"beforeOpeningCurlyBrace": true | ||
}, | ||
"requireSpacesInForStatement": true, | ||
"requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, | ||
"requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, | ||
"requireSpacesInsideArrayBrackets": "all", | ||
"requireSpacesInsideObjectBrackets": "all", | ||
"validateCommentPosition": { "position": "above", "allExcept": [ "pragma" ] }, | ||
"validateIndentation": 2, | ||
"validateParameterSeparator": ", ", | ||
"validateQuoteMarks": { "mark": "\"", "escape": true } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"expr": true, | ||
"esversion": 6, | ||
"futurehostile": true, | ||
"predef": [ "-Promise" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
language: node_js | ||
node_js: | ||
- "6" | ||
- "5" | ||
script: | ||
- grunt | ||
deploy: | ||
provider: npm | ||
api_key: | ||
secure: lUv5YgSSvuW8OfTHkvkRaq6wyyobzy1ewQ2XsBIINxYUnqBL3iN+UNvuqJ2dZibwuaXbBB0HXT5/w1HQAykvTjeXi9VwrFJk6v1IoS1tUIm48Ln4OBY67UkYIiZFEAl3Sh73yxUxbQmSjJP9vtV877t5eeb0cn4cTaRhUVBHpLU6XXeR8Sl343C6Xwy+EJ+ZP4SRcJ/pu/Ze1uvC5ys9BN1o1L8anFeNDJL58BMmExy3WcAKUyKPl7jSzMfhTeGT1AjH2BVuOyPsansqLqxxKVtSOGvxaQkH/ubhwKdQOVMUZ/hFYFy+O8aIvwTNUpHvhQRBw6KIUH7QBLONVDUcdBn6xQWebdq6551ujEMyB9WTxs5MaOzHEbEx4prnSuNBg3MD+0Zzh8qugn5rtjG/T0YvhrsMp6o5rYpcmceCBY6PiLGnCxTetqgzfIjNt+RtU7dwDFWBHIn7sRZa/CyQ4zD0Ohq2c0KHevp2Pbr85cS7J9EBsC+qbbsYXWwzgqSNVa60cCYAiGcQuRzBkJDOu4wi8/til6hLhhXkENj0ei4lgJBqnRwsHF6R3vl9UyNtEY243xAwfEmpVT99dw1khzxLWpkGvJq7+zrFUJYo8XpSnRmNz9HLgip70NN9DU1CB500Ym7qtmARaTDRJQXkgBTqKm7KdGOAXSZ0Djv69Mg= | ||
on: | ||
tags: true | ||
branch: master | ||
node: "5" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
module.exports = function(grunt) { | ||
// Project configuration. | ||
grunt.initConfig({ | ||
// Loads values from package.json so they can be used within this file. | ||
pkg: grunt.file.readJSON("package.json"), | ||
// JSHint checks code quality. | ||
jshint: { | ||
files: [ "src/**/*.js", "!node_modules/**", "!coverage/**" ], | ||
options: { | ||
jshintrc: true | ||
} | ||
}, | ||
// JSCS checks code style against standards. | ||
jscs: { | ||
main: [ "src/**/*.js", "!node_modules/**", "!coverage/**" ] | ||
}, | ||
// Mocha is a test framework for node.js. | ||
mochaTest: { | ||
options: { | ||
timeout: 30000 | ||
}, | ||
test: { | ||
src: [ "src/test/**/*.js" ] | ||
} | ||
}, | ||
// Istanbul is a code coverage tool for use with Mocha. | ||
mocha_istanbul: { // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers | ||
coverage: { | ||
src: "src/test/**/*.js", | ||
options: { | ||
istanbulOptions: [ "--include-all-sources" ] | ||
} | ||
} | ||
} | ||
}); | ||
|
||
grunt.loadNpmTasks("grunt-contrib-jshint"); | ||
grunt.loadNpmTasks("grunt-jscs"); | ||
grunt.loadNpmTasks("grunt-mocha-test"); | ||
grunt.loadNpmTasks("grunt-mocha-istanbul"); | ||
|
||
// Default task(s). | ||
grunt.registerTask("default", [ "jshint", "jscs", "test", "coverage" ]); | ||
grunt.registerTask("test", [ "mochaTest:test" ]); | ||
grunt.registerTask("coverage", [ "mocha_istanbul" ]); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "cache-manager-express-mw", | ||
"version": "0.0.1", | ||
"description": "Middleware for Express that uses cache-manager to add a caching layer in front of your application.", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/afrasso/cache-manager-express-mw.git" | ||
}, | ||
"keywords": [ | ||
"cache-manager", | ||
"express", | ||
"cache" | ||
], | ||
"author": "Anthony Frasso", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/afrasso/cache-manager-express-mw/issues" | ||
}, | ||
"homepage": "https://github.com/afrasso/cache-manager-express-mw#readme", | ||
"devDependencies": { | ||
"grunt": "^1.0.1", | ||
"grunt-contrib-jshint": "^1.0.0", | ||
"grunt-jscs": "^3.0.1", | ||
"grunt-mocha-istanbul": "^5.0.2", | ||
"grunt-mocha-test": "^0.12.7", | ||
"mocha": "^3.0.2", | ||
"mocha-istanbul": "^0.3.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
var _ = require("lodash"), | ||
Promise = require("bluebird"); | ||
|
||
var caching = function(cache, options) { | ||
var prefix = options && options.prefix ? `${options.prefix}:` : ""; | ||
var cacheControlAccessibility = | ||
options && options.cacheControlAccessibility ? options.cacheControlAccessibility : "public"; | ||
|
||
var getMaxAge = function(res) { | ||
var cacheControlHeader = res.get("Cache-Control"); | ||
if (!cacheControlHeader) { | ||
return; | ||
} | ||
var match = cacheControlHeader.match(/.*max-age=(\d+).*/); | ||
if (!match || match.length < 2) { | ||
return; | ||
} | ||
var maxAge = parseInt(match[1]); | ||
return maxAge; | ||
}; | ||
|
||
var getValue = function(key) { | ||
return new Promise(function(resolve, reject) { | ||
cache.get(key, function(err, result) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
var getTtl = function(key) { | ||
if (typeof cache.ttl !== "function") { | ||
return Promise.resolve(); | ||
} | ||
return new Promise(function(resolve, reject) { | ||
cache.ttl(key, function(err, result) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(result); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
var setCacheControlHeader = function(res, ttl) { | ||
if (ttl) { | ||
res.set("Cache-Control", `${cacheControlAccessibility}, max-age=${ttl}`); | ||
} | ||
}; | ||
|
||
var handleCacheHit = function(res, key, value) { | ||
getTtl(key) | ||
.then(ttl => setCacheControlHeader(res, ttl)) | ||
.then(x => { | ||
// This is dumb, but it results in a prettier JSON format | ||
try { | ||
var obj = JSON.parse(value.body); | ||
res.status(value.statusCode).json(obj); | ||
} catch (error) { | ||
res.status(value.statusCode).send(value.body); | ||
} | ||
}); | ||
}; | ||
|
||
var handleCacheMiss = function(res, key) { | ||
var send = res.send.bind(res); | ||
|
||
res.send = function(body) { | ||
var ret = send(body); | ||
|
||
if (/^2/.test(res.statusCode)) { | ||
cache.set(key, { statusCode: res.statusCode, body: body }, { ttl: getMaxAge(res) }); | ||
} | ||
|
||
return ret; | ||
}; | ||
}; | ||
|
||
var middleware = function(req, res, next) { | ||
if (!cache) { | ||
next(); | ||
return; | ||
} | ||
|
||
var query = _.assign({ }, options.defaults, req.query); | ||
var sortedQueryString = _(query).keys().sortBy().map(key => `${key}=${query[key]}`).join("&"); | ||
var key = `${prefix}${req.method}:${req.path}?${sortedQueryString}`; | ||
|
||
getValue(key) | ||
.then(value => { | ||
if (value) { | ||
handleCacheHit(res, key, value); | ||
} else { | ||
handleCacheMiss(res, key); | ||
next(); | ||
} | ||
}); | ||
}; | ||
|
||
return middleware; | ||
}; | ||
|
||
module.exports = caching; |