Files
bruno/tests/ssl/custom-ca-certs/server/index.js
lohit 0b3f5100e7 fix: recreate HTTP/HTTPS agents on redirect to prevent stale agent reuse (#7597) (#7615)
When a request redirected from HTTP to HTTPS (or vice versa), the
original httpAgent/httpsAgent leaked into the redirect config. The
httpsAgent — which carries custom CA certificates and TLS options — was
never created for the redirect URL, causing UNABLE_TO_VERIFY_LEAF_SIGNATURE.

Changes:
- setupProxyAgents (electron) now deletes stale agents at the top of
  every call so they are always recreated for the current URL
- setupProxyAgents extracted to bruno-cli/proxy-util.js (mirrors the
  electron version) and called on every redirect in the CLI path
- Removed the else-branch in bruno-requests/http-https-agents.ts that
  only created one agent based on initial protocol
- Added HTTP→HTTPS redirect test server and request to the
  custom-ca-certs SSL test suite
2026-04-01 20:55:28 +05:30

146 lines
3.9 KiB
JavaScript

#!/usr/bin/env node
const path = require('node:path');
const fs = require('node:fs');
const http = require('node:http');
const https = require('node:https');
const WebSocket = require('ws');
const { killProcessOnPort } = require('./helpers/platform');
function createServer(certsDir, port = 8090) {
const serverOptions = {
key: fs.readFileSync(path.join(certsDir, 'localhost-key.pem')),
cert: fs.readFileSync(path.join(certsDir, 'localhost-cert.pem')),
ca: fs.readFileSync(path.join(certsDir, 'ca-cert.pem'))
};
const server = https.createServer(serverOptions, (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
res.end('helloworld');
});
// Create WebSocket server for WSS support
const wss = new WebSocket.Server({ noServer: true });
wss.on('connection', function connection(ws, request) {
ws.on('error', function error(err) {
console.error('WebSocket error:', err.message);
});
ws.on('message', function message(data) {
const msg = Buffer.from(data).toString().trim();
let isJSON = false;
let obj = {};
try {
obj = JSON.parse(msg);
isJSON = true;
} catch (err) {
// Not a JSON value
}
if (isJSON) {
if ('func' in obj && obj.func === 'headers') {
return ws.send(JSON.stringify({
headers: request.headers
}));
} else if ('func' in obj && obj.func === 'query') {
const url = new URL(request.url, `https://${request.headers.host}`);
const query = Object.fromEntries(url.searchParams.entries());
return ws.send(JSON.stringify({
query: query
}));
} else {
return ws.send(JSON.stringify({
data: obj
}));
}
}
return ws.send(Buffer.from(data).toString());
});
});
// Handle WebSocket upgrade requests
server.on('upgrade', (request, socket, head) => {
if (request.url.startsWith('/ws')) {
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request);
});
} else {
socket.destroy();
}
});
return new Promise((resolve, reject) => {
server.listen(port, (error) => {
if (error) {
reject(error);
} else {
resolve(server);
}
});
});
}
function createHttpRedirectServer(httpsPort, httpPort = 8091) {
const server = http.createServer((req, res) => {
const redirectUrl = `https://localhost:${httpsPort}${req.url}`;
res.writeHead(301, { Location: redirectUrl });
res.end();
});
return new Promise((resolve, reject) => {
server.listen(httpPort, (error) => {
if (error) reject(error);
else resolve(server);
});
});
}
function shutdownServer(server, cleanup) {
const shutdown = (signal) => {
console.log(`🛑 Received ${signal}, shutting down`);
if (cleanup) cleanup();
if (server) {
server.close(() => process.exit(0));
} else {
process.exit(0);
}
};
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
}
async function startServer() {
const certsDir = path.join(__dirname, 'certs');
const port = 8090;
console.log('🚀 Starting HTTPS test server');
try {
killProcessOnPort(port);
killProcessOnPort(8091);
console.log(`🌐 Creating server on port ${port}`);
const server = await createServer(certsDir, port);
console.log(`🌐 Creating HTTP redirect server on port 8091 → ${port}`);
const httpRedirectServer = await createHttpRedirectServer(port);
shutdownServer(server, () => {
httpRedirectServer.close();
console.log('✨ Server cleanup completed');
});
} catch (error) {
console.error('❌ Server startup failed:', error.message);
process.exit(1);
}
}
if (require.main === module) {
startServer();
}
module.exports = { startServer };