-
-
Save stickystyle/a35fa8bc7461018aad83 to your computer and use it in GitHub Desktop.
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
require('dotenv').load(); | |
var debug = require('debug')('asproxy'); | |
var express = require('express'); | |
var request = require("request"); | |
var redis = require('redis'); | |
var httpProxy = require('http-proxy'); | |
var expressJwt = require('express-jwt'); //https://npmjs.org/package/express-jwt | |
var cors = require('cors'); | |
debug("Starting application"); | |
var server_port = process.env.SERVER_PORT || 5050; | |
debug("Initializing express"); | |
var app = express(); | |
app.use(require('morgan')("dev")); | |
app.use(require('compression')()); | |
app.use(require('response-time')()); | |
app.use(require('body-parser').json()); | |
app.use(cors()); | |
app.options('*', cors()); | |
app.use(function(err, req, res, next){ | |
if (err.constructor.name === 'UnauthorizedError') { | |
res.status(401).send('Unauthorized'); | |
} | |
}); | |
debug("Initializing proxy"); | |
var proxy = httpProxy.createProxyServer({}); | |
proxy.on('proxyReq', function(proxyReq, req, res, options) { | |
proxyReq.setHeader('x-tenant-id', process.env.TENANT_ID); | |
proxyReq.setHeader('x-cache-bypass', 1); //Don't want to be mixing up double cache | |
debug("proxyReq user: %s", req.user.sub); | |
if (req.user) { | |
proxyReq.setHeader('x-jwt-user', req.user.app_metadata.wms_user); | |
proxyReq.setHeader('x-jwt-authz', req.user.app_metadata.wms_authz); | |
} | |
}); | |
debug("Initializing redis"); | |
var redisClient = redis.createClient(process.env.REDIS_URL); | |
var jwtCheck = expressJwt({ | |
secret: new Buffer('XXXXXXXXXXX', 'base64'), | |
audience: 'XXXXXXXXXX' | |
}); | |
function proxyRequest(req, res) { | |
debug("Proxying request for %s", req.url); | |
req.url = req.url.replace('/tenants/'+process.env.TENANT_ID, ''); | |
debug("Proxying request to %s%s", process.env.PROXY_TARGET, req.url); | |
proxy.web(req, res, { target: process.env.PROXY_TARGET }); | |
} | |
function handleCachedRes(reply, req, res) { | |
var jres = JSON.parse(reply); | |
jres.headers['content-type'] = jres['mimeType']; | |
jres.headers['x-cache-hit'] = 'HIT'; | |
if (jres.headers.ETag == req.headers['if-none-match']) { | |
debug('Client sent matching ETag: %s', jres.headers.ETag); | |
res.writeHead(304, jres.headers); | |
res.end(""); | |
} else { | |
debug('Returning cached Redis data for url: %s', req.url); | |
res.writeHead(200, jres.headers); | |
res.end(JSON.stringify(jres.returnval)); | |
} | |
} | |
function checkBodyCache(req, res) { | |
redisClient.get(req.url, function(err, reply) { | |
if (reply === null) { | |
debug('Redis body cache for url: %s NOT found', req.url); | |
proxyRequest(req, res); | |
} else { | |
debug('Redis body cache for url: %s found', req.url); | |
handleCachedRes(reply, req, res); | |
} | |
}); | |
} | |
app.get('/tenants/*', jwtCheck, function (req, res) { | |
debug("GET: Requested URL: %s", req.url); | |
debug("JWT token: %j", req.user); | |
if (!req.user.sub) { | |
res.statusCode = 401; | |
res.json({ message: "Not Authorized", rel:"https://XXXXXX" }); | |
} else { | |
var key = "AUTHZ:"+req.user.app_metadata.wms_authz+":"+req.url; | |
debug('AUTHZ Redis key %s', key); | |
redisClient.get(key, function(err, reply) { | |
if (reply == null) { | |
debug('AUTHZ Redis key NOT found'); | |
proxyRequest(req, res); | |
} else { | |
debug('AUTHZ Redis key found'); | |
checkBodyCache(req, res, reply); | |
} | |
}); | |
} | |
}); | |
app.post('/tenants/*', jwtCheck, function (req, res) { | |
debug("POST: Requested URL: %s", req.url); | |
debug("JWT token: %j", req.user); | |
if (!req.user.sub) { | |
res.statusCode = 401; | |
res.json({ message: "Not Authorized", rel:"https://XXXXX" }); | |
} else { | |
proxyRequest(req, res); | |
} | |
}); | |
app.put('/tenants/*', jwtCheck, function (req, res) { | |
debug("PUT: Requested URL: %s", req.url); | |
debug("JWT token: %j", req.user); | |
if (!req.user.sub) { | |
res.statusCode = 401; | |
res.json({ message: "Not Authorized", rel:"https://XXXXXXX" }); | |
} else { | |
proxyRequest(req, res); | |
} | |
}); | |
app.delete('/tenants/*', jwtCheck, function (req, res) { | |
debug("DELETE: Requested URL: %s", req.url); | |
debug("JWT token: %j", req.user); | |
if (!req.user.sub) { | |
res.statusCode = 401; | |
res.json({ message: "Not Authorized", rel:"https://XXXXXXX" }); | |
} else { | |
proxyRequest(req, res); | |
} | |
}); | |
app.head('/tenants/*', jwtCheck, function (req, res) { | |
debug("Requested URL: %s", req.url); | |
debug("JWT token: %j", req.user); | |
if (!req.user.sub) { | |
res.statusCode = 401; | |
res.json({ message: "Not Authorized", rel:"https://XXXXXXX" }); | |
} else { | |
proxyRequest(req, res); | |
} | |
}); | |
app.listen(server_port, function () { | |
console.log('listening on http://localhost:'+server_port); | |
}); |
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
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
{ | |
"name": "asproxy", | |
"version": "0.1.0", | |
"description": "Proxy for airstream that queries the redis cache", | |
"main": "app.js", | |
"dependencies": { | |
"body-parser": "^1.14.0", | |
"compression": "^1.5.2", | |
"cors": "^2.7.1", | |
"debug": "^2.2.0", | |
"dotenv": "^1.2.0", | |
"express": "^4.13.3", | |
"express-jwt": "^3.1.0", | |
"http-proxy": "^1.11.3", | |
"jsonwebtoken": "^5.0.5", | |
"morgan": "^1.6.1", | |
"redis": "^2.0.0", | |
"request": "^2.63.0", | |
"response-time": "^2.3.1" | |
}, | |
"devDependencies": {}, | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1", | |
"start": "node app.js" | |
}, | |
"author": "Ryan Parrish <[email protected]>", | |
"license": "UNLICENSED" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Application that works with 1.11.3, but not 1.12.0. Simple proxy that layers JWT and some caching on top of a legacy API.