diff --git a/ironhead/app/gateway/article.js b/ironhead/app/gateway/article.js
deleted file mode 100644
index f2bcbd8..0000000
--- a/ironhead/app/gateway/article.js
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-module.exports = function () {
- return {
- configKeys: ['article']
- }
-}
diff --git a/ironhead/app/hooks/gateway/init.js b/ironhead/app/hooks/gateway/init.js
deleted file mode 100644
index 421a9f4..0000000
--- a/ironhead/app/hooks/gateway/init.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const { fixtures, get } = require('../../../lib/package/ease/orchestrator');
-/**
- *
- * @description **init** is the wrapper over ease for initiating the fixtures
- * path.
- *
- *
- * In order to send request using ease , we need to initialize
- * the config path, which ease keeps it in memory.
- *
- *
- * Application using knucklehead , needs to initialize it in the beginning
- * since fixturing is asynchronous.
- *
- * @param { fixturesPath } fixturesPath - absolute config path needs to be provided.
- * It's not a mandatory field otherwise it will bootstrap using the default EASE_CONFIG_PATH
- *
- * @returns { Promise } Promise - ConfigPath promise is returned
- */
-const init = (fixturesPath) => {
- if (!fixturesPath) throw new Error('Fixtures Path for Gateway initalization not passed.');
- const configPath = fixturesPath;
- global.easeDispatch = get;
- return fixtures(configPath);
-};
-
-module.exports = init;
diff --git a/ironhead/app/hooks/httpClient.js b/ironhead/app/hooks/httpClient.js
new file mode 100644
index 0000000..02b8526
--- /dev/null
+++ b/ironhead/app/hooks/httpClient.js
@@ -0,0 +1,13 @@
+const path = require('path');
+const httpClient = require('../../lib/package/gateway/httpClient');
+
+const CONFIG_PATH = path.join(__dirname, '../../config/http-client');
+
+module.exports = async (app, cb) => {
+ try {
+ await httpClient.init(CONFIG_PATH);
+ cb();
+ } catch (e) {
+ cb(e);
+ }
+};
diff --git a/ironhead/app/hooks/index.js b/ironhead/app/hooks/index.js
index e187035..5357be5 100644
--- a/ironhead/app/hooks/index.js
+++ b/ironhead/app/hooks/index.js
@@ -1,7 +1,9 @@
-const init = require('./init');
+const httpClient = require('./httpClient');
+const redis = require('./redis');
const hooks = [
- init
+ redis,
+ httpClient
];
module.exports = hooks;
diff --git a/ironhead/app/hooks/init.js b/ironhead/app/hooks/init.js
deleted file mode 100644
index b32c723..0000000
--- a/ironhead/app/hooks/init.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const path = require('path');
-const gateway = require('./gateway/init');
-
-const CONFIG_PATH = path.join(__dirname, '../../config/ease-config');
-
-module.exports = async (app, cb) => {
- try {
- await gateway(CONFIG_PATH);
- cb();
- } catch (e) {
- cb(e);
- }
-};
diff --git a/ironhead/app/hooks/redis.js b/ironhead/app/hooks/redis.js
new file mode 100644
index 0000000..331728f
--- /dev/null
+++ b/ironhead/app/hooks/redis.js
@@ -0,0 +1,10 @@
+const { init } = require('../../lib/package/adapter/redis');
+
+module.exports = async (app, cb) => {
+ try {
+ await init();
+ cb();
+ } catch (e) {
+ cb(e);
+ }
+};
\ No newline at end of file
diff --git a/ironhead/app/modules/story/gatewayConfig.js b/ironhead/app/modules/story/gatewayConfig.js
new file mode 100644
index 0000000..eb82752
--- /dev/null
+++ b/ironhead/app/modules/story/gatewayConfig.js
@@ -0,0 +1,16 @@
+exports.article = {
+ options: {
+ server: 'api',
+ method: 'get',
+ endPoint: '/v2/everything?domains=wsj.com,nytimes.com'
+ }
+};
+
+exports.gateway = () => (
+ {
+ ttl: 60,
+ type: 'rest',
+ cache: true,
+ configKeys: ['article']
+ }
+);
\ No newline at end of file
diff --git a/ironhead/app/modules/story/routes/article.js b/ironhead/app/modules/story/route.js
similarity index 76%
rename from ironhead/app/modules/story/routes/article.js
rename to ironhead/app/modules/story/route.js
index d3366f2..3f214a0 100644
--- a/ironhead/app/modules/story/routes/article.js
+++ b/ironhead/app/modules/story/route.js
@@ -1,4 +1,4 @@
-const gateway = require('../../../gateway/article');
+const { gateway } = require('./gatewayConfig');
module.exports = {
domain: 'article',
diff --git a/ironhead/app/routes/index.js b/ironhead/app/routes/index.js
index f0c21d0..10be513 100644
--- a/ironhead/app/routes/index.js
+++ b/ironhead/app/routes/index.js
@@ -1,4 +1,4 @@
-const article = require('../modules/story/routes/article');
+const article = require('../modules/story/route');
const routes = [
article
diff --git a/ironhead/config/config.js b/ironhead/config/config.js
index e268fe7..291fcbd 100644
--- a/ironhead/config/config.js
+++ b/ironhead/config/config.js
@@ -1,7 +1,9 @@
const session = require('./session');
const static = require('./static');
+const gateway = require('./gateway');
module.exports = {
static,
+ gateway,
...session
};
diff --git a/ironhead/config/ease-config/ease/getConfig.js b/ironhead/config/ease-config/ease/getConfig.js
deleted file mode 100644
index 8292cbf..0000000
--- a/ironhead/config/ease-config/ease/getConfig.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const article = {
- options: {
- server: 'api',
- method: 'get',
- endPoint: '/v2/everything?domains=wsj.com,nytimes.com'
- }
-}
-
-module.exports = {
- article
-};
diff --git a/ironhead/config/gateway.js b/ironhead/config/gateway.js
new file mode 100644
index 0000000..d343624
--- /dev/null
+++ b/ironhead/config/gateway.js
@@ -0,0 +1,3 @@
+const gateway = require('../lib/package/gateway');
+
+module.exports = gateway;
\ No newline at end of file
diff --git a/ironhead/config/http-client/ease/getConfig.js b/ironhead/config/http-client/ease/getConfig.js
new file mode 100644
index 0000000..80c1419
--- /dev/null
+++ b/ironhead/config/http-client/ease/getConfig.js
@@ -0,0 +1,5 @@
+const { article } = require('../../../app/modules/story/gatewayConfig');
+
+module.exports = {
+ article
+};
diff --git a/ironhead/config/ease-config/header/index.js b/ironhead/config/http-client/header/index.js
similarity index 100%
rename from ironhead/config/ease-config/header/index.js
rename to ironhead/config/http-client/header/index.js
diff --git a/ironhead/config/ease-config/server/development.js b/ironhead/config/http-client/server/development.js
similarity index 100%
rename from ironhead/config/ease-config/server/development.js
rename to ironhead/config/http-client/server/development.js
diff --git a/ironhead/config/ease-config/server/production.js b/ironhead/config/http-client/server/production.js
similarity index 100%
rename from ironhead/config/ease-config/server/production.js
rename to ironhead/config/http-client/server/production.js
diff --git a/ironhead/config/ease-config/server/staging.js b/ironhead/config/http-client/server/staging.js
similarity index 100%
rename from ironhead/config/ease-config/server/staging.js
rename to ironhead/config/http-client/server/staging.js
diff --git a/ironhead/lib/package/adapter/redis/index.js b/ironhead/lib/package/adapter/redis/index.js
new file mode 100644
index 0000000..627dfc9
--- /dev/null
+++ b/ironhead/lib/package/adapter/redis/index.js
@@ -0,0 +1,28 @@
+const Redis = require('ioredis');
+Redis.Promise = require('bluebird')
+
+let connection;
+
+module.exports = {
+ init() {
+ if (connection) {
+ return Promise.resolve(connection);
+ }
+ return new Promise((resolve, reject) => {
+ connection = new Redis();
+ connection.set('testRedisConnection', 'test data');
+ connection.get('testRedisConnection', function (err, data) {
+ if (err) {
+ reject(err);
+ } else {
+ if (data === 'test data') {
+ resolve(connection);
+ }
+ }
+ });
+ });
+ },
+ getConnection() {
+ return connection;
+ }
+};
diff --git a/ironhead/lib/package/gateway/cacheClient.js b/ironhead/lib/package/gateway/cacheClient.js
new file mode 100644
index 0000000..55acb79
--- /dev/null
+++ b/ironhead/lib/package/gateway/cacheClient.js
@@ -0,0 +1,22 @@
+const { generateKey } = require('./util');
+const { getConnection } = require('../adapter/redis');
+
+const get = async (config) => {
+ const key = generateKey(JSON.stringify(config));
+ const redis = getConnection();
+ const data = await redis.get(key);
+
+ return data;
+};
+
+const set = (config, response) => {
+ const { ttl } = config;
+ const key = generateKey(JSON.stringify(config));
+ const redis = getConnection();
+ return setTimeout(() => redis.set(key, JSON.stringify(response), 'ex', ttl), 0);
+};
+
+module.exports = {
+ get,
+ set
+};
diff --git a/ironhead/lib/package/gateway/httpClient.js b/ironhead/lib/package/gateway/httpClient.js
new file mode 100644
index 0000000..e75ecf1
--- /dev/null
+++ b/ironhead/lib/package/gateway/httpClient.js
@@ -0,0 +1,59 @@
+const { fixtures, get } = require('../ease/orchestrator');
+/**
+ *
+ * @description **init** is the wrapper over ease for initiating the fixtures
+ * path.
+ *
+ *
+ * In order to send request using ease , we need to initialize
+ * the config path, which ease keeps it in memory.
+ *
+ *
+ * Application using knucklehead , needs to initialize it in the beginning
+ * since fixturing is asynchronous.
+ *
+ * @param { fixturesPath } fixturesPath - absolute config path needs to be provided.
+ * It's not a mandatory field otherwise it will bootstrap using the default EASE_CONFIG_PATH
+ *
+ * @returns { Promise } Promise - ConfigPath promise is returned
+ */
+const init = (fixturesPath) => {
+ if (!fixturesPath) throw new Error('Fixtures Path for Gateway initialization not passed.');
+ const configPath = fixturesPath;
+ return fixtures(configPath);
+};
+
+const sanitize = (configKeys, response) => {
+ const isMulti = configKeys.length > 1;
+
+ if (isMulti) {
+ const parsedResponse = configKeys.reduce((acc, key) => {
+ const { [key]: { statusCode, body } } = response;
+ acc[key] = {
+ ...body,
+ apiStatusCode: statusCode
+ };
+ return acc;
+ }, {});
+
+ return parsedResponse;
+ }
+ const [singleKeyName] = configKeys;
+ const { [singleKeyName]: { statusCode, body } } = response;
+ return {
+ ...body,
+ apiStatusCode: statusCode
+ };
+};
+
+const request = async ({ configKeys, reqConfig, handlers }) => {
+ const httpResponse = await get(configKeys, reqConfig);
+ const parsedResponse = sanitize(configKeys, httpResponse);
+ const standardResponse = typeof handler === 'function' ? handler(parsedResponse) : parsedResponse;
+ return standardResponse;
+}
+
+module.exports = {
+ init,
+ request
+};
diff --git a/ironhead/lib/package/gateway/index.js b/ironhead/lib/package/gateway/index.js
new file mode 100644
index 0000000..36097d6
--- /dev/null
+++ b/ironhead/lib/package/gateway/index.js
@@ -0,0 +1,30 @@
+const httpClient = require('./httpClient');
+const cacheClient = require('./cacheClient');
+
+module.exports = async (props) => {
+ const { reqConfig, ...gwConfig } = props;
+ const { configKeys, cache } = gwConfig;
+
+ try {
+ if (cache) {
+ const data = await cacheClient.get(gwConfig);
+
+ if (data) {
+ console.log('hit');
+ const response = JSON.parse(data);
+ return response;
+ }
+ console.log('miss');
+ const response = await httpClient.request(props);
+ cacheClient.set(gwConfig, response);
+ return response;
+ } else {
+ const response = await httpClient.request(props);
+ return response;
+ }
+
+ } catch (e) {
+ throw e;
+ }
+};
+
diff --git a/ironhead/lib/package/gateway/util.js b/ironhead/lib/package/gateway/util.js
new file mode 100644
index 0000000..1c38c0d
--- /dev/null
+++ b/ironhead/lib/package/gateway/util.js
@@ -0,0 +1,7 @@
+const crypto = require('crypto');
+
+exports.generateKey = (text) => {
+ const hash = crypto.createHash('md5');
+ hash.update(text);
+ return hash.digest('hex');
+};
diff --git a/ironhead/package-lock.json b/ironhead/package-lock.json
index 1acfbc1..4ec03ed 100644
--- a/ironhead/package-lock.json
+++ b/ironhead/package-lock.json
@@ -2973,6 +2973,11 @@
}
}
},
+ "cluster-key-slot": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.12.tgz",
+ "integrity": "sha512-21O0kGmvED5OJ7ZTdqQ5lQQ+sjuez33R+d35jZKLwqUb5mqcPHUsxOSzj61+LHVtxGZd1kShbQM3MjB/gBJkVg=="
+ },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -4026,6 +4031,11 @@
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"dev": true
},
+ "denque": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.0.tgz",
+ "integrity": "sha512-gh513ac7aiKrAgjiIBWZG0EASyDF9p4JMWwKA8YU5s9figrL5SRNEMT6FDynsegakuhWd1wVqTvqvqAoDxw7wQ=="
+ },
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -5354,6 +5364,11 @@
"write": "0.2.1"
}
},
+ "flexbuffer": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/flexbuffer/-/flexbuffer-0.0.6.tgz",
+ "integrity": "sha1-A5/fI/iCPkQMOPMnfm/vEXQhWzA="
+ },
"flush-write-stream": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
@@ -6622,6 +6637,38 @@
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
+ "ioredis": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.6.2.tgz",
+ "integrity": "sha512-zlc/LeoeriHTXm5z3rakPcfRcUV9x+xr0E+7/L7KH0D5z7sI5ngEQWR2RUxnwFcxUcCkvrXMztRIdBP3DhqMAQ==",
+ "requires": {
+ "cluster-key-slot": "1.0.12",
+ "debug": "3.2.6",
+ "denque": "1.4.0",
+ "flexbuffer": "0.0.6",
+ "lodash.defaults": "4.2.0",
+ "lodash.flatten": "4.4.0",
+ "redis-commands": "1.4.0",
+ "redis-errors": "1.2.0",
+ "redis-parser": "3.0.0",
+ "standard-as-callback": "1.0.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
"ip-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-3.0.0.tgz",
@@ -8179,6 +8226,16 @@
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
},
+ "lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
+ },
+ "lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -11917,6 +11974,24 @@
}
}
},
+ "redis-commands": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz",
+ "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw=="
+ },
+ "redis-errors": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
+ },
+ "redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
+ "requires": {
+ "redis-errors": "1.2.0"
+ }
+ },
"regenerate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
@@ -13148,6 +13223,11 @@
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz",
"integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA=="
},
+ "standard-as-callback": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-1.0.2.tgz",
+ "integrity": "sha512-1Qrah+2Vmj8DiftcXR9gfUe/gFmOukdnxF5v7G/apCZbLtjh3rjss8Eu6Qlprm6zerrl+qDmvm7KXpJedqpoAQ=="
+ },
"static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
diff --git a/ironhead/package.json b/ironhead/package.json
index 90297b3..17f4d7a 100644
--- a/ironhead/package.json
+++ b/ironhead/package.json
@@ -15,6 +15,7 @@
"body-parser": "^1.18.3",
"cookie-parser": "^1.4.3",
"css-loader": "^1.0.1",
+ "ioredis": "^4.6.2",
"preact": "^8.4.2",
"preact-render-to-string": "^4.1.0",
"preact-router": "^2.6.1",
diff --git a/ironhead/public/src/components/header/index.js b/ironhead/public/src/components/header/index.js
index 0958451..90bdb85 100644
--- a/ironhead/public/src/components/header/index.js
+++ b/ironhead/public/src/components/header/index.js
@@ -1,10 +1,12 @@
import { h } from 'preact';
import './header.scss';
-const HeaderLayout = (props) => (
+const HeaderLayout = props => (