mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
95 lines
2.4 KiB
JavaScript
95 lines
2.4 KiB
JavaScript
import * as http from "http";
|
|
import * as https from "https";
|
|
import { ui } from "../environment/userInteraction.js";
|
|
|
|
/**
|
|
* @param {import("http").IncomingMessage} req
|
|
* @param {import("http").ServerResponse} res
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
export function handleHttpProxyRequest(req, res) {
|
|
if (!req.url) {
|
|
ui.writeError("Safe-chain: Request missing URL");
|
|
res.writeHead(400, "Bad Request");
|
|
res.end("Bad Request: Missing URL");
|
|
return;
|
|
}
|
|
|
|
const url = new URL(req.url);
|
|
|
|
// The protocol for the plainHttpProxy should usually only be http:
|
|
// but when the client for some reason sends an https: request directly
|
|
// instead of using the CONNECT method, we should handle it gracefully.
|
|
let protocol;
|
|
if (url.protocol === "http:") {
|
|
protocol = http;
|
|
} else if (url.protocol === "https:") {
|
|
protocol = https;
|
|
} else {
|
|
res.writeHead(502);
|
|
res.end(`Bad Gateway: Unsupported protocol ${url.protocol}`);
|
|
return;
|
|
}
|
|
|
|
const proxyRequest = protocol
|
|
.request(
|
|
req.url,
|
|
{ method: req.method, headers: req.headers },
|
|
(proxyRes) => {
|
|
if (!proxyRes.statusCode) {
|
|
ui.writeError("Safe-chain: Proxy response missing status code");
|
|
res.writeHead(500);
|
|
res.end("Internal Server Error");
|
|
return;
|
|
}
|
|
|
|
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
proxyRes.pipe(res);
|
|
|
|
proxyRes.on("error", () => {
|
|
// Proxy response stream error
|
|
// Clean up client response stream
|
|
if (res.writable) {
|
|
res.end();
|
|
}
|
|
});
|
|
|
|
proxyRes.on("close", () => {
|
|
// Clean up if the proxy response stream closes
|
|
if (res.writable) {
|
|
res.end();
|
|
}
|
|
});
|
|
}
|
|
)
|
|
.on("error", (err) => {
|
|
if (!res.headersSent) {
|
|
res.writeHead(502);
|
|
res.end(`Bad Gateway: ${err.message}`);
|
|
} else {
|
|
// Headers already sent, just destroy the response
|
|
res.destroy();
|
|
}
|
|
});
|
|
|
|
req.on("error", () => {
|
|
// Client request stream error
|
|
// Abort the proxy request
|
|
proxyRequest.destroy();
|
|
});
|
|
|
|
res.on("error", () => {
|
|
// Client response stream error (client disconnected)
|
|
// Clean up proxy streams
|
|
proxyRequest.destroy();
|
|
});
|
|
|
|
res.on("close", () => {
|
|
// Client disconnected
|
|
// Abort the proxy request to avoid unnecessary work
|
|
proxyRequest.destroy();
|
|
});
|
|
|
|
req.pipe(proxyRequest);
|
|
}
|