mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-13 16:57:27 +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 { destr } from 'destr';
|
||||||
import { config } from '@/config';
|
import ofetch from '@/utils/ofetch';
|
||||||
import got, { CancelableRequest, Response as GotResponse, OptionsInit, Options, Got } from 'got';
|
|
||||||
|
|
||||||
type Response<T> = GotResponse<string> & {
|
const gotofetch = ofetch.create({
|
||||||
data: T;
|
parseResponse: (responseText) => ({
|
||||||
status: number;
|
data: destr(responseText),
|
||||||
};
|
body: responseText,
|
||||||
|
}),
|
||||||
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;
|
const getFakeGot = (defaultOptions?: any) => {
|
||||||
export type { Response, Options } from 'got';
|
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",
|
"crypto-js": "4.2.0",
|
||||||
"currency-symbol-map": "5.1.0",
|
"currency-symbol-map": "5.1.0",
|
||||||
"dayjs": "1.11.8",
|
"dayjs": "1.11.8",
|
||||||
|
"destr": "2.0.3",
|
||||||
"directory-import": "3.2.1",
|
"directory-import": "3.2.1",
|
||||||
"dotenv": "16.4.5",
|
"dotenv": "16.4.5",
|
||||||
"entities": "4.5.0",
|
"entities": "4.5.0",
|
||||||
@@ -89,6 +90,7 @@
|
|||||||
"module-alias": "2.2.3",
|
"module-alias": "2.2.3",
|
||||||
"notion-to-md": "3.1.1",
|
"notion-to-md": "3.1.1",
|
||||||
"oauth-1.0a": "2.2.6",
|
"oauth-1.0a": "2.2.6",
|
||||||
|
"ofetch": "1.3.4",
|
||||||
"otplib": "12.0.1",
|
"otplib": "12.0.1",
|
||||||
"pac-proxy-agent": "7.0.1",
|
"pac-proxy-agent": "7.0.1",
|
||||||
"proxy-chain": "2.4.0",
|
"proxy-chain": "2.4.0",
|
||||||
|
|||||||
Generated
+26
@@ -53,6 +53,9 @@ dependencies:
|
|||||||
dayjs:
|
dayjs:
|
||||||
specifier: 1.11.8
|
specifier: 1.11.8
|
||||||
version: 1.11.8
|
version: 1.11.8
|
||||||
|
destr:
|
||||||
|
specifier: 2.0.3
|
||||||
|
version: 2.0.3
|
||||||
directory-import:
|
directory-import:
|
||||||
specifier: 3.2.1
|
specifier: 3.2.1
|
||||||
version: 3.2.1
|
version: 3.2.1
|
||||||
@@ -131,6 +134,9 @@ dependencies:
|
|||||||
oauth-1.0a:
|
oauth-1.0a:
|
||||||
specifier: 2.2.6
|
specifier: 2.2.6
|
||||||
version: 2.2.6
|
version: 2.2.6
|
||||||
|
ofetch:
|
||||||
|
specifier: 1.3.4
|
||||||
|
version: 1.3.4
|
||||||
otplib:
|
otplib:
|
||||||
specifier: 12.0.1
|
specifier: 12.0.1
|
||||||
version: 12.0.1
|
version: 12.0.1
|
||||||
@@ -4085,6 +4091,10 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/destr@2.0.3:
|
||||||
|
resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/detect-libc@2.0.2:
|
/detect-libc@2.0.2:
|
||||||
resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
|
resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -6798,6 +6808,10 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/node-fetch-native@1.6.4:
|
||||||
|
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-fetch@2.7.0:
|
/node-fetch@2.7.0:
|
||||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
engines: {node: 4.x || >=6.0.0}
|
engines: {node: 4.x || >=6.0.0}
|
||||||
@@ -6920,6 +6934,14 @@ packages:
|
|||||||
/object-inspect@1.13.1:
|
/object-inspect@1.13.1:
|
||||||
resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
|
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:
|
/on-exit-leak-free@2.1.2:
|
||||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -8764,6 +8786,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==}
|
resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/ufo@1.5.3:
|
||||||
|
resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/uglify-js@3.4.10:
|
/uglify-js@3.4.10:
|
||||||
resolution: {integrity: sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==}
|
resolution: {integrity: sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
|
|||||||
Reference in New Issue
Block a user