Skip to content

Instantly share code, notes, and snippets.

@monochromer
Created October 31, 2023 06:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monochromer/c702543645cc2224e11de7583e85b2f9 to your computer and use it in GitHub Desktop.
Save monochromer/c702543645cc2224e11de7583e85b2f9 to your computer and use it in GitHub Desktop.
Node.js simple HTTP proxy
const http = require('node:http')
const https = require('node:https')
const events = require('node:events')
const stream = require('node:stream/promises')
const { env } = process
http
.createServer(async (clientRequest, clientResponse) => {
try {
const url = new URL(clientRequest.url, env.BASE_URL)
const httpModule = url.protocol === 'https:' ? https : http
const serverRequest = httpModule.request(url, {
method: http.request.method,
headers: Object.assign({}, clientRequest.headers, { host: url.host })
})
const requestPipeline = stream.pipeline(clientRequest, serverRequest)
const [serverResponse] = await events.once(serverRequest, 'response')
clientResponse.writeHead(serverResponse.statusCode, serverResponse.headers)
const responsePipeline = stream.pipeline(serverResponse, clientResponse)
await Promise.all([requestPipeline, responsePipeline])
} catch (error) {
// handle `premature close` and `aborted` errors
console.error(clientRequest.url, error.message)
if (!clientResponse.headersSent) {
clientResponse
.writeHead(500, { 'content-type': 'text/plain' })
.end(error.message)
} else {
clientResponse.end()
}
}
})
.listen(env.PORT)
.on('listening', function () {
const address = this.address()
const bind = typeof address === 'string'
? 'pipe ' + address
: 'port ' + address.port
console.log('Listening on ' + bind)
})
.on('error', function (error) {
if (error.syscall !== 'listen') {
throw error
}
const bind = typeof env.PORT === 'string'
? 'pipe ' + port
: 'port ' + port
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges')
process.exit(1)
case 'EADDRINUSE':
console.error(bind + ' is already in use')
process.exit(1)
default:
throw error
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment