Skip to content

Instantly share code, notes, and snippets.

@stickystyle
Last active November 21, 2015 22:11
Show Gist options
  • Save stickystyle/a35fa8bc7461018aad83 to your computer and use it in GitHub Desktop.
Save stickystyle/a35fa8bc7461018aad83 to your computer and use it in GitHub Desktop.
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);
});
[email protected] /Users/rparrish/workingfolder/asproxy
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ ├─┬ [email protected]
│ │ │ │ │ ├── [email protected]
│ │ │ │ │ ├── [email protected]
│ │ │ │ │ └── [email protected]
│ │ │ │ └── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected] (git+https://github.com/rynomad/jsbn.git#bb522b0124f75424f89d49446c40a87111942c7b)
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
└─┬ [email protected]
├── [email protected]
└── [email protected]
{
"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"
}
@stickystyle
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment