Add HTTP redirect following support

- Add followRedirects option in Transport (enabled by default)
- Add redirectCount to limit redirects to 3
- Detect and follow 301/302/307/308 redirects
- Add forceHttps parameter for redirect handling
- Log redirects when verbose mode is enabled
This commit is contained in:
2026-04-03 21:39:20 -05:00
parent 97cb5078e2
commit 5f0fce2c33

View File

@@ -241,6 +241,7 @@ interface TransportOptions {
connectTimeout?: number | undefined;
timeout?: number | undefined;
useHttps?: boolean;
followRedirects?: boolean;
}
interface JsonRpcRequest {
@@ -267,6 +268,8 @@ export class Transport {
private connectTimeout: number;
private timeout: number;
private useHttps: boolean;
private followRedirects: boolean;
private redirectCount: number;
constructor(options: TransportOptions = {}) {
this.fingerprints = options.fingerprints || null;
@@ -276,6 +279,8 @@ export class Transport {
this.connectTimeout = options.connectTimeout || CONNECT_TIMEOUT;
this.timeout = options.timeout || DEFAULT_TIMEOUT;
this.useHttps = options.useHttps || false;
this.followRedirects = options.followRedirects ?? true;
this.redirectCount = 0;
}
/**
@@ -291,6 +296,21 @@ export class Transport {
handler: string,
requestData: string,
verbose: boolean = false
): Promise<JsonRpcResponse> {
// Reset redirect count for each new request
this.redirectCount = 0;
return this.doRequest(host, handler, requestData, verbose);
}
/**
* Internal method to make HTTP request with redirect support
*/
private async doRequest(
host: string,
handler: string,
requestData: string,
verbose: boolean = false,
forceHttps?: boolean
): Promise<JsonRpcResponse> {
// Detect protocol based on port or explicit protocol
const hostParts = host.split(":");
@@ -299,6 +319,7 @@ export class Transport {
// Use HTTPS if explicitly configured, or for standard HTTPS ports
const shouldUseHttps =
forceHttps === true ||
this.useHttps ||
port === 443 ||
port === 8443 ||
@@ -364,6 +385,49 @@ export class Transport {
res.on("end", () => {
try {
// Handle redirects BEFORE parsing response body
const statusCode = res.statusCode;
if (
this.followRedirects &&
statusCode &&
this.redirectCount < 3 &&
[301, 302, 307, 308].includes(statusCode)
) {
const location = res.headers["location"];
if (location) {
this.redirectCount++;
if (verbose) {
console.log(
`🔄 Redirect (${statusCode}): ${host}${handler}${location}`
);
}
try {
const redirectUrl = new URL(
location,
`http://${host}`
);
const newHost = redirectUrl.host;
const newUseHttps =
redirectUrl.protocol === "https:";
this.doRequest(
newHost,
handler,
requestData,
verbose,
newUseHttps
)
.then(resolve)
.catch(reject);
return;
} catch (redirectError) {
reject(redirectError);
return;
}
}
}
// Handle compression
const encoding = res.headers["content-encoding"];
let responseText: string;