Skip to content

Instantly share code, notes, and snippets.

@rajivnarayana
Created February 11, 2022 16:20
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 rajivnarayana/3fedfef0ea42780bc9d50d819c845d34 to your computer and use it in GitHub Desktop.
Save rajivnarayana/3fedfef0ea42780bc9d50d819c845d34 to your computer and use it in GitHub Desktop.
A No dependency http proxy

A http proxy with no dependencies running on default port 4000.

Proxy

Any request to /licipoapi/proxy will be proxied to the destination end point. Request body should have to be wrapped in data variable and the url should also be passed in the body.

{
  "data" : <...actual body...>,
  "url": "https://original-url.example.com"
}

Response body will be wrapped in data and will have to be unwrapped.

const http = require("http");
const https = require("https");
const PORT = process.env.PORT || 4000;
class APIError extends Error {
constructor(message, code = 400) {
super(message);
this.code = code;
}
}
http.createServer(async (req, res) => {
const buffers = [];
for await (const chunk of req) {
buffers.push(chunk);
}
const data = Buffer.concat(buffers).toString();
if (data) {
req.body = JSON.parse(data);
}
try {
if (req.url === "/licipoapi/proxy") {
if (req.method === "OPTIONS") {
res.writeHead(200, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, apikey",
"Access-Control-Max-Age": "3600"
});
res.end();
return;
}
const authorizationHeader = req.headers.authorization;
const apiKey = req.headers.apikey;
if (!authorizationHeader) {
throw new APIError("Unauthorized", 401);
}
const {url: endPoint, data: body} = req.body;
const protocol = endPoint.startsWith("https") ? https : http;
console.log(`Request method : ${req.method} to ${endPoint}`);
const proxyReq = protocol.request(endPoint, {
headers: {
authorization: authorizationHeader,
apikey: apiKey,
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(JSON.stringify(body))
},
method: "GET",
}, (proxyRes) => {
const _buffers = [];
proxyRes.on("data", (chunk) => {
_buffers.push(chunk);
});
proxyRes.on("end", () => {
const _data = Buffer.concat(_buffers).toString();
console.log(_data);
if (+proxyRes.statusCode === 200) {
const parsedData = JSON.parse(_data);
const _modifiedResponse = JSON.stringify({ data: parsedData});
const {"content-length": contentLength, ...others} = proxyRes.headers;
res.writeHead(proxyRes.statusCode, {'Access-Control-Allow-Origin': "*", ...others, 'Content-Length': Buffer.byteLength(_modifiedResponse)});
res.write(_modifiedResponse);
} else {
res.writeHead(proxyRes.statusCode, {'Access-Control-Allow-Origin': "*", ...proxyRes.headers});
res.write(_data);
}
res.end();
});
});
proxyReq.on("error", (err) => {
console.error(err);
res.writeHead(500);
res.write(err.message);
res.end();
});
proxyReq.write(JSON.stringify(body));
proxyReq.end();
}
} catch (error) {
if (error instanceof APIError) {
res.writeHead(error.code);
res.write(error.message);
} else {
res.writeHead(400);
res.write(error.message);
}
res.end();
}
}).listen(PORT);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment