Skip to content

Instantly share code, notes, and snippets.

@callumgare
Created April 29, 2022 06:24
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 callumgare/0e4799fcb732c34a57c537f4aa416d11 to your computer and use it in GitHub Desktop.
Save callumgare/0e4799fcb732c34a57c537f4aa416d11 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
// This script allows you to forward http requests to a http proxy. There might not seem like much point to
// a proxy to another proxy but requests to a standard http proxy must be in a certain format. Strapi
// doesn't currently support this so we can use this proxy to forward requests in a format that Strapi
// is capable of sending.
// Requests can be made http://localhost:<port used by this script>/<full url include domain of the target page>
// For example if you start this script with the port 8080 and you ultimately want send a request to
// https://www.infoxchange.org/au/about-us you would send the request to
// http://localhost:8080/https://www.infoxchange.org/au/about-us
const http = require("http")
const httpProxy = require("http-proxy")
const URL = require("url").URL;
const args = process.argv.slice(2)
const port = getPortFromArgs('port')
const mockProxyServerPort = getPortFromArgs('mock-proxy-server-port')
const proxyServerUrl = !mockProxyServerPort
? process.env.HTTP_PROXY
: `http://localhost:${mockProxyServerPort}`
if (!port) {
console.error('Please provide the port to use as a cli flag in the form of: --port=<port>')
process.exit(1)
}
if (!proxyServerUrl) {
console.error('Please set the HTTP_PROXY env var to provide URL of the proxy server to forward requests.')
process.exit(1)
}
function getPortFromArgs(cliFlag) {
const portArg = args.find(arg => arg.startsWith(`--${cliFlag}=`))
let port = null
if (portArg) {
const [, strPort] = portArg.match(/=(\d+)$/)
port = parseInt(strPort) || null
}
return port
}
const proxy = httpProxy.createProxyServer({});
const server = http.createServer(function (req, res) {
req.url = req.url.replace(/^\//, '')
try {
new URL(req.url)
} catch (error) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.write('Invalid request: url should be in the form of <domain of proxy>/<domain of target site><path of target site>');
res.end();
return
}
proxy.web(
req,
res,
{
target: proxyServerUrl,
toProxy: true,
prependPath: false
}
);
})
proxy.on('proxyReq', function(proxyReq, req, res, options) {
const reqUrl = new URL(req.url)
proxyReq.setHeader('Host', reqUrl.host);
});
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Error reaching HTTP_PROXY.');
});
console.log(`Proxy sever listening on port ${port} and sending to ${proxyServerUrl}`)
server.listen(port);
if (mockProxyServerPort) {
startMockHttpProxy(mockProxyServerPort)
}
// This can be used for testing and will act as a standard http proxy
function startMockHttpProxy(port) {
const proxy = httpProxy.createProxyServer({});
const server = http.createServer(function(req, res) {
const reqUrl = new URL(req.url)
const domainToSendTo = `${reqUrl.protocol}//${reqUrl.host}`
// req.url is the value used in the path of the http request.
// Normally this would just be exactly that, a path. But requests
// to http proxies have the domain of the target site prepending
// this path. We don't have to worry about striping away the domain
// when we forward this request to the target site since http-proxy
// will do this for us so long as the `toProxy` isn't set to true.
proxy.web(req, res, { target: domainToSendTo });
});
console.log(`Mock HTTP Proxy sever listening on port ${port}`)
server.listen(port);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment