Skip to content

Instantly share code, notes, and snippets.

@nondanee
Last active February 14, 2022 06:14
Show Gist options
  • Save nondanee/31c60cae0012d24bf738f543fccfd0b2 to your computer and use it in GitHub Desktop.
Save nondanee/31c60cae0012d24bf738f543fccfd0b2 to your computer and use it in GitHub Desktop.
a proxy pipe server
const URL = require('url')
const http = require('http')
const https = require('https')
const {
PORT = 8080,
HTTP_PROXY = 'https://username:password@localhost:443',
} = process.env
const proxy = URL.parse(HTTP_PROXY)
const proxyHeaders = { 'proxy-authorization': `Basic ${Buffer.from(proxy.auth).toString('base64')}` }
delete proxy.auth
const server = http.createServer().listen(PORT)
const destroy = (...sockets) => (
sockets.forEach(socket => { try { socket.destroy() } catch (_) {} })
)
server.on('request', (req, res) => {
const { method, url, headers, socket } = req
if (!/^http:\/\//.test(url)) {
res.writeHead(400)
res.end()
return
}
const proxyReq = (proxy.protocol === 'http:' ? http : https)
.request({
...proxy,
method,
path: url,
headers: {
...headers,
...proxyHeaders,
},
servername: proxy.hostname,
})
.on('error', () => {
destroy(proxyReq.socket, socket)
})
.on('response', proxyRes => {
res
.on('error', () => {
destroy(proxyReq.socket, socket)
})
.writeHead(proxyRes.statusCode, proxyRes.headers)
proxyRes
.on('error', () => {
destroy(proxyReq.socket, socket)
})
.pipe(res)
})
req
.on('error', () => {
destroy(socket, proxyReq.socket)
})
.pipe(proxyReq)
})
server.on('connect', (req, socket, head) => {
const { url, headers } = req
const proxyReq = (proxy.protocol === 'http:' ? http : https)
.request({
...proxy,
method: 'CONNECT',
path: url,
headers: {
...headers,
...proxyHeaders,
},
servername: proxy.hostname,
})
.on('error', () => {
destroy(socket, proxyReq.socket)
})
.on('connect', (_, proxySocket) => {
socket.on('error', () => destroy(socket, proxySocket))
proxySocket.on('error', () => destroy(socket, proxySocket))
socket.write('HTTP/1.1 200 Connection established\r\n\r\n')
proxySocket.write(head)
proxySocket.pipe(socket)
socket.pipe(proxySocket)
})
.end()
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment