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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user