Allow the safe-chain to act as a regular http proxy too (besides the CONNECT tunneling implementation)

This commit is contained in:
Sander Declerck 2025-10-13 15:49:42 +02:00
parent 5eedbfb57f
commit 8ed2330a3c
No known key found for this signature in database
2 changed files with 60 additions and 7 deletions

View file

@ -0,0 +1,58 @@
import * as http from "http";
import * as https from "https";
export function handleHttpProxyRequest(req, res) {
const url = new URL(req.url);
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) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers);
proxyRes.pipe(res);
proxyRes.on("error", () => {
// Stream error while piping response
// Response headers already sent, can't send error status
});
}
)
.on("error", (err) => {
res.writeHead(502);
res.end(`Bad Gateway: ${err.message}`);
});
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
if (!res.writableEnded) {
proxyRequest.destroy();
}
});
req.pipe(proxyRequest);
}

View file

@ -1,6 +1,7 @@
import * as http from "http"; import * as http from "http";
import { tunnelRequest } from "./tunnelRequestHandler.js"; import { tunnelRequest } from "./tunnelRequestHandler.js";
import { mitmConnect } from "./mitmRequestHandler.js"; import { mitmConnect } from "./mitmRequestHandler.js";
import { handleHttpProxyRequest } from "./plainHttpProxy.js";
import { getCaCertPath } from "./certUtils.js"; import { getCaCertPath } from "./certUtils.js";
import { auditChanges } from "../scanning/audit/index.js"; import { auditChanges } from "../scanning/audit/index.js";
import { knownRegistries, parsePackageFromUrl } from "./parsePackageFromUrl.js"; import { knownRegistries, parsePackageFromUrl } from "./parsePackageFromUrl.js";
@ -54,13 +55,7 @@ export function mergeSafeChainProxyEnvironmentVariables(env) {
} }
function createProxyServer() { function createProxyServer() {
const server = http.createServer((_, res) => { const server = http.createServer(handleHttpProxyRequest);
res.writeHead(400, "Bad Request");
res.write(
"Safe-chain proxy: Direct http not supported. Only CONNECT requests are allowed."
);
res.end();
});
return server; return server;
} }