mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-08-30 16:55:08 +08:00
feat: use ofetch imitate got
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import logger from '@/utils/logger';
|
||||
import { config } from '@/config';
|
||||
import got, { CancelableRequest, Response as GotResponse, OptionsInit, Options, Got } from 'got';
|
||||
|
||||
type Response<T> = GotResponse<string> & {
|
||||
data: T;
|
||||
status: number;
|
||||
};
|
||||
|
||||
type GotRequestFunction = {
|
||||
(url: string | URL, options?: Options): CancelableRequest<Response<Record<string, any>>>;
|
||||
<T>(url: string | URL, options?: Options): CancelableRequest<Response<T>>;
|
||||
(options: Options): CancelableRequest<Response<Record<string, any>>>;
|
||||
<T>(options: Options): CancelableRequest<Response<T>>;
|
||||
};
|
||||
|
||||
// @ts-expect-error got instance with custom response type
|
||||
const custom: {
|
||||
all?: <T>(list: Array<Promise<T>>) => Promise<Array<T>>;
|
||||
get: GotRequestFunction;
|
||||
post: GotRequestFunction;
|
||||
put: GotRequestFunction;
|
||||
patch: GotRequestFunction;
|
||||
head: GotRequestFunction;
|
||||
delete: GotRequestFunction;
|
||||
} & GotRequestFunction &
|
||||
Got = got.extend({
|
||||
retry: {
|
||||
limit: config.requestRetry,
|
||||
statusCodes: [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, 521, 522, 524],
|
||||
},
|
||||
hooks: {
|
||||
beforeRetry: [
|
||||
(err, count) => {
|
||||
logger.error(`Request ${err.options.url} fail, retry attempt #${count}: ${err}`);
|
||||
},
|
||||
],
|
||||
beforeRedirect: [
|
||||
(options, response) => {
|
||||
logger.http(`Redirecting to ${options.url} for ${response.requestUrl}`);
|
||||
},
|
||||
],
|
||||
afterResponse: [
|
||||
// @ts-expect-error custom response type
|
||||
(response: Response<Record<string, any>>) => {
|
||||
try {
|
||||
response.data = typeof response.body === 'string' ? JSON.parse(response.body) : response.body;
|
||||
} catch {
|
||||
// @ts-expect-error for compatibility
|
||||
response.data = response.body;
|
||||
}
|
||||
response.status = response.statusCode;
|
||||
return response;
|
||||
},
|
||||
],
|
||||
init: [
|
||||
(
|
||||
options: OptionsInit & {
|
||||
data?: string;
|
||||
}
|
||||
) => {
|
||||
// compatible with axios api
|
||||
if (options && options.data) {
|
||||
options.body = options.body || options.data;
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
headers: {
|
||||
'user-agent': config.ua,
|
||||
},
|
||||
timeout: {
|
||||
request: config.requestTimeout,
|
||||
},
|
||||
});
|
||||
custom.all = (list) => Promise.all(list);
|
||||
|
||||
export default custom;
|
||||
export type { Response, Options } from 'got';
|
||||
+57
-76
@@ -1,79 +1,60 @@
|
||||
import logger from '@/utils/logger';
|
||||
import { config } from '@/config';
|
||||
import got, { CancelableRequest, Response as GotResponse, OptionsInit, Options, Got } from 'got';
|
||||
import { destr } from 'destr';
|
||||
import ofetch from '@/utils/ofetch';
|
||||
|
||||
type Response<T> = GotResponse<string> & {
|
||||
data: T;
|
||||
status: number;
|
||||
};
|
||||
|
||||
type GotRequestFunction = {
|
||||
(url: string | URL, options?: Options): CancelableRequest<Response<Record<string, any>>>;
|
||||
<T>(url: string | URL, options?: Options): CancelableRequest<Response<T>>;
|
||||
(options: Options): CancelableRequest<Response<Record<string, any>>>;
|
||||
<T>(options: Options): CancelableRequest<Response<T>>;
|
||||
};
|
||||
|
||||
// @ts-expect-error got instance with custom response type
|
||||
const custom: {
|
||||
all?: <T>(list: Array<Promise<T>>) => Promise<Array<T>>;
|
||||
get: GotRequestFunction;
|
||||
post: GotRequestFunction;
|
||||
put: GotRequestFunction;
|
||||
patch: GotRequestFunction;
|
||||
head: GotRequestFunction;
|
||||
delete: GotRequestFunction;
|
||||
} & GotRequestFunction &
|
||||
Got = got.extend({
|
||||
retry: {
|
||||
limit: config.requestRetry,
|
||||
statusCodes: [400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 421, 422, 423, 424, 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511, 521, 522, 524],
|
||||
},
|
||||
hooks: {
|
||||
beforeRetry: [
|
||||
(err, count) => {
|
||||
logger.error(`Request ${err.options.url} fail, retry attempt #${count}: ${err}`);
|
||||
},
|
||||
],
|
||||
beforeRedirect: [
|
||||
(options, response) => {
|
||||
logger.http(`Redirecting to ${options.url} for ${response.requestUrl}`);
|
||||
},
|
||||
],
|
||||
afterResponse: [
|
||||
// @ts-expect-error custom response type
|
||||
(response: Response<Record<string, any>>) => {
|
||||
try {
|
||||
response.data = typeof response.body === 'string' ? JSON.parse(response.body) : response.body;
|
||||
} catch {
|
||||
// @ts-expect-error for compatibility
|
||||
response.data = response.body;
|
||||
}
|
||||
response.status = response.statusCode;
|
||||
return response;
|
||||
},
|
||||
],
|
||||
init: [
|
||||
(
|
||||
options: OptionsInit & {
|
||||
data?: string;
|
||||
}
|
||||
) => {
|
||||
// compatible with axios api
|
||||
if (options && options.data) {
|
||||
options.body = options.body || options.data;
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
headers: {
|
||||
'user-agent': config.ua,
|
||||
},
|
||||
timeout: {
|
||||
request: config.requestTimeout,
|
||||
},
|
||||
const gotofetch = ofetch.create({
|
||||
parseResponse: (responseText) => ({
|
||||
data: destr(responseText),
|
||||
body: responseText,
|
||||
}),
|
||||
});
|
||||
custom.all = (list) => Promise.all(list);
|
||||
|
||||
export default custom;
|
||||
export type { Response, Options } from 'got';
|
||||
const getFakeGot = (defaultOptions?: any) => {
|
||||
const fakeGot = (request, options) => {
|
||||
if (options?.hooks?.beforeRequest) {
|
||||
for (const hook of options.hooks.beforeRequest) {
|
||||
hook(options);
|
||||
}
|
||||
}
|
||||
if (!(typeof request === 'string' || request instanceof Request) && request.url) {
|
||||
options = {
|
||||
...request,
|
||||
...options,
|
||||
};
|
||||
request = request.url;
|
||||
}
|
||||
|
||||
options = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options?.json && !options.body) {
|
||||
options.body = options.json;
|
||||
}
|
||||
if (options?.form && !options.body) {
|
||||
const body = new FormData();
|
||||
for (const key in options.form) {
|
||||
body.append(key, options.form[key]);
|
||||
}
|
||||
options.body = body;
|
||||
if (!options.headers) {
|
||||
options.headers = {};
|
||||
}
|
||||
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
return gotofetch(request, options);
|
||||
};
|
||||
|
||||
fakeGot.get = (request, options) => fakeGot(request, { ...options, method: 'GET' });
|
||||
fakeGot.post = (request, options) => fakeGot(request, { ...options, method: 'POST' });
|
||||
fakeGot.put = (request, options) => fakeGot(request, { ...options, method: 'PUT' });
|
||||
fakeGot.patch = (request, options) => fakeGot(request, { ...options, method: 'PATCH' });
|
||||
fakeGot.head = (request, options) => fakeGot(request, { ...options, method: 'HEAD' });
|
||||
fakeGot.delete = (request, options) => fakeGot(request, { ...options, method: 'DELETE' });
|
||||
fakeGot.extend = (options) => getFakeGot(options);
|
||||
|
||||
return fakeGot;
|
||||
};
|
||||
|
||||
export default getFakeGot();
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ofetch } from 'ofetch';
|
||||
import { config } from '@/config';
|
||||
import logger from '@/utils/logger';
|
||||
|
||||
const rofetch = ofetch.create({
|
||||
retry: config.requestRetry,
|
||||
retryDelay: 1000,
|
||||
timeout: config.requestTimeout,
|
||||
headers: {
|
||||
'user-agent': config.ua,
|
||||
},
|
||||
onRequestError({ request, error }) {
|
||||
logger.error(`Request ${request.url} fail: ${error}`);
|
||||
},
|
||||
});
|
||||
|
||||
export default rofetch;
|
||||
@@ -63,6 +63,7 @@
|
||||
"crypto-js": "4.2.0",
|
||||
"currency-symbol-map": "5.1.0",
|
||||
"dayjs": "1.11.8",
|
||||
"destr": "2.0.3",
|
||||
"directory-import": "3.2.1",
|
||||
"dotenv": "16.4.5",
|
||||
"entities": "4.5.0",
|
||||
@@ -89,6 +90,7 @@
|
||||
"module-alias": "2.2.3",
|
||||
"notion-to-md": "3.1.1",
|
||||
"oauth-1.0a": "2.2.6",
|
||||
"ofetch": "1.3.4",
|
||||
"otplib": "12.0.1",
|
||||
"pac-proxy-agent": "7.0.1",
|
||||
"proxy-chain": "2.4.0",
|
||||
|
||||
Generated
+26
@@ -53,6 +53,9 @@ dependencies:
|
||||
dayjs:
|
||||
specifier: 1.11.8
|
||||
version: 1.11.8
|
||||
destr:
|
||||
specifier: 2.0.3
|
||||
version: 2.0.3
|
||||
directory-import:
|
||||
specifier: 3.2.1
|
||||
version: 3.2.1
|
||||
@@ -131,6 +134,9 @@ dependencies:
|
||||
oauth-1.0a:
|
||||
specifier: 2.2.6
|
||||
version: 2.2.6
|
||||
ofetch:
|
||||
specifier: 1.3.4
|
||||
version: 1.3.4
|
||||
otplib:
|
||||
specifier: 12.0.1
|
||||
version: 12.0.1
|
||||
@@ -4085,6 +4091,10 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/destr@2.0.3:
|
||||
resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==}
|
||||
dev: false
|
||||
|
||||
/detect-libc@2.0.2:
|
||||
resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -6798,6 +6808,10 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/node-fetch-native@1.6.4:
|
||||
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
|
||||
dev: false
|
||||
|
||||
/node-fetch@2.7.0:
|
||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
@@ -6920,6 +6934,14 @@ packages:
|
||||
/object-inspect@1.13.1:
|
||||
resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
|
||||
|
||||
/ofetch@1.3.4:
|
||||
resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==}
|
||||
dependencies:
|
||||
destr: 2.0.3
|
||||
node-fetch-native: 1.6.4
|
||||
ufo: 1.5.3
|
||||
dev: false
|
||||
|
||||
/on-exit-leak-free@2.1.2:
|
||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -8764,6 +8786,10 @@ packages:
|
||||
resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==}
|
||||
dev: true
|
||||
|
||||
/ufo@1.5.3:
|
||||
resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
|
||||
dev: false
|
||||
|
||||
/uglify-js@3.4.10:
|
||||
resolution: {integrity: sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
|
||||
Reference in New Issue
Block a user