Last active
July 1, 2020 09:02
-
-
Save evanlucas/245f6841c6518eb4bb223a80ce744a3e to your computer and use it in GitHub Desktop.
Node proxy
This file contains hidden or 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
'use strict' | |
const http = require('http') | |
const url = require('url') | |
function random(ar) { | |
return ar[Math.floor(Math.random() * ar.length)] | |
} | |
function createDownstream() { | |
return new Promise((resolve, reject) => { | |
const server = http.createServer(handle) | |
const headers = [ | |
'x-biscuits' | |
, 'x-toast' | |
, 'x-javascript' | |
, 'x-twitter' | |
] | |
function handle(req, res) { | |
const header = random(headers) | |
res.writeHead(200, { | |
[header]: 'HI' | |
}) | |
res.end('DOWNSTREAM') | |
} | |
const done = (err) => { | |
server.removeListener('error', done) | |
server.removeListener('listening', done) | |
if (err) return reject(err) | |
resolve(server) | |
} | |
server.on('error', done) | |
server.on('listening', done) | |
server.listen() | |
}) | |
} | |
let port | |
let downstream_url | |
async function main() { | |
const downstream = await createDownstream() | |
port = downstream.address().port | |
console.log('listen downstream', port) | |
downstream_url = `http://localhost:${port}` | |
const server = http.createServer(proxy) | |
server.listen(() => { | |
const p = server.address().port | |
console.log('service listen', p) | |
console.log('make a few requests to', `http://localhost:${p}`) | |
console.log('like this:') | |
console.log(` curl http://localhost:${p}`) | |
}) | |
server.on('error', console.error) | |
} | |
main().catch((err) => { | |
process.nextTick(() => { | |
throw err | |
}) | |
}) | |
function proxy(req, res) { | |
const outbound = url.parse(downstream_url) | |
outbound.method = req.method | |
outbound.path = outbound.pathname = req.url | |
outbound.headers = { | |
connection: 'close' | |
} | |
// Add more headers here if you want | |
const proxy = http.request(outbound) | |
const onError = (err) => { | |
console.log('onError', err) | |
} | |
proxy.on('error', onError) | |
req.on('error', onError) | |
req.on('aborted', () => { | |
proxy.abort() | |
}) | |
proxy.once('response', (proxy_res) => { | |
console.log('got response', proxy_res.statusCode, proxy_res.headers) | |
res.statusCode = proxy_res.statusCode | |
// Add your logic here to determine if you should takeover | |
if (proxy_res.headers['x-biscuits']) { | |
// take over | |
// This reads the response into memory. | |
// You probably want to use a transform stream though if possible to | |
// reduce memory pressure | |
let buf = '' | |
proxy_res.on('data', (chunk) => { | |
buf += chunk.toString() | |
}) | |
proxy_res.on('end', () => { | |
// Lowercase the result and then split it into characters | |
// `DOWNSTREAM` becomes `d o w n s t r e a m` | |
buf = buf.toLowerCase().split('').join(' ') | |
res.end(buf) | |
}) | |
} else { | |
proxy_res.pipe(res) | |
} | |
}) | |
req.pipe(proxy) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment