feat: add support for request redirection and abort signal handling
This commit is contained in:
parent
3f1effbb4a
commit
65f1707358
16
dist/index.js
vendored
16
dist/index.js
vendored
@ -27,8 +27,10 @@ const readData = (res, mode) => new Promise((resolve, reject) => {
|
||||
})
|
||||
.on("error", reject);
|
||||
});
|
||||
export default async (urlString, options = {}) => {
|
||||
const fetch = async (urlString, options = {}, redirectCount = 0) => {
|
||||
const { protocol, hostname, pathname, search, port } = new URL(urlString);
|
||||
if (options.signal?.aborted)
|
||||
throw new Error("Request aborted");
|
||||
const body = options.method === "POST" && options.body
|
||||
? options.headers?.["Content-Type"] === "application/json"
|
||||
? JSON.stringify(options.body)
|
||||
@ -48,6 +50,11 @@ export default async (urlString, options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requester = protocol === "https:" ? https : http;
|
||||
const req = requester.request(requestOptions, res => {
|
||||
if (options.followRedirects && res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
if (redirectCount >= (options.maxRedirects || 5))
|
||||
return reject(new Error("Max redirects exceeded"));
|
||||
return resolve(fetch(new URL(res.headers.location, urlString).toString(), options, redirectCount + 1));
|
||||
}
|
||||
if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300))
|
||||
return reject(new Error(`Request failed with status code ${res.statusCode}`));
|
||||
resolve({
|
||||
@ -64,8 +71,15 @@ export default async (urlString, options = {}) => {
|
||||
reject(new Error("Request timed out"));
|
||||
});
|
||||
req.on("error", reject);
|
||||
if (options.signal) {
|
||||
options.signal.addEventListener("abort", () => {
|
||||
req.destroy(new Error("Request aborted"));
|
||||
reject(new Error("Request aborted"));
|
||||
});
|
||||
}
|
||||
if (body)
|
||||
req.write(body);
|
||||
req.end();
|
||||
});
|
||||
};
|
||||
export default fetch;
|
||||
|
27
src/index.ts
27
src/index.ts
@ -16,6 +16,9 @@ type ResponseData = {
|
||||
interface ExtendedRequestOptions extends http.RequestOptions {
|
||||
body?: any;
|
||||
timeout?: number;
|
||||
followRedirects?: boolean;
|
||||
maxRedirects?: number;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
const decompress = (
|
||||
@ -53,12 +56,16 @@ const readData = <T>(
|
||||
.on("error", reject);
|
||||
});
|
||||
|
||||
export default async (
|
||||
const fetch = async (
|
||||
urlString: string,
|
||||
options: ExtendedRequestOptions = {}
|
||||
options: ExtendedRequestOptions = {},
|
||||
redirectCount: number = 0
|
||||
): Promise<ResponseData> => {
|
||||
const { protocol, hostname, pathname, search, port } = new URL(urlString);
|
||||
|
||||
if(options.signal?.aborted)
|
||||
throw new Error("Request aborted");
|
||||
|
||||
const body =
|
||||
options.method === "POST" && options.body
|
||||
? options.headers?.["Content-Type"] === "application/json"
|
||||
@ -81,6 +88,12 @@ export default async (
|
||||
return new Promise((resolve, reject) => {
|
||||
const requester = protocol === "https:" ? https : http;
|
||||
const req = requester.request(requestOptions, res => {
|
||||
if(options.followRedirects && res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
if(redirectCount >= (options.maxRedirects || 5))
|
||||
return reject(new Error("Max redirects exceeded"));
|
||||
return resolve(fetch(new URL(res.headers.location, urlString).toString(), options, redirectCount + 1));
|
||||
}
|
||||
|
||||
if(res.statusCode && (res.statusCode < 200 || res.statusCode >= 300))
|
||||
return reject(new Error(`Request failed with status code ${res.statusCode}`));
|
||||
resolve({
|
||||
@ -99,8 +112,18 @@ export default async (
|
||||
});
|
||||
|
||||
req.on("error", reject);
|
||||
|
||||
if(options.signal) {
|
||||
options.signal.addEventListener("abort", () => {
|
||||
req.destroy(new Error("Request aborted"));
|
||||
reject(new Error("Request aborted"));
|
||||
});
|
||||
}
|
||||
|
||||
if(body)
|
||||
req.write(body);
|
||||
req.end();
|
||||
});
|
||||
};
|
||||
|
||||
export default fetch;
|
||||
|
Loading…
x
Reference in New Issue
Block a user