2020-04-17 20:31:22 +00:00
|
|
|
const fetch = require('node-fetch');
|
|
|
|
const fs = require('fs');
|
|
|
|
const crypto = require('crypto');
|
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
function md5(str) {
|
|
|
|
return crypto.createHash('md5').update(str).digest('hex');
|
|
|
|
}
|
|
|
|
|
2020-11-28 02:46:49 +00:00
|
|
|
class Response {
|
|
|
|
constructor(raw, cacheFilePath) {
|
|
|
|
Object.assign(this, raw);
|
|
|
|
this.cacheFilePath = cacheFilePath;
|
2020-04-17 20:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
text() {
|
2020-11-28 02:46:49 +00:00
|
|
|
return this.bodyBuffer.toString();
|
2020-04-17 20:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
json() {
|
2020-11-28 02:46:49 +00:00
|
|
|
return JSON.parse(this.bodyBuffer.toString());
|
2020-04-17 20:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
buffer() {
|
2020-11-28 02:46:49 +00:00
|
|
|
return this.bodyBuffer;
|
2020-04-17 20:31:22 +00:00
|
|
|
}
|
|
|
|
|
2020-11-28 02:46:49 +00:00
|
|
|
ejectFromCache() {
|
|
|
|
return fs.promises.unlink(this.cacheFilePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function createRawResponse(fetchRes) {
|
|
|
|
const buffer = await fetchRes.buffer();
|
|
|
|
|
|
|
|
return {
|
|
|
|
status: fetchRes.status,
|
|
|
|
statusText: fetchRes.statusText,
|
|
|
|
type: fetchRes.type,
|
|
|
|
url: fetchRes.url,
|
|
|
|
useFinalURL: fetchRes.useFinalURL,
|
|
|
|
ok: fetchRes.ok,
|
|
|
|
headers: fetchRes.headers,
|
|
|
|
redirected: fetchRes.redirected,
|
|
|
|
bodyBuffer: buffer,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getResponse(cacheDirPath, requestArguments) {
|
|
|
|
const [url, requestInit, ...rest] = requestArguments;
|
|
|
|
const requestParams = requestInit.body
|
|
|
|
? ({ ...requestInit, body: typeof requestInit.body === 'object' ? requestInit.body.toString() : requestInit.body })
|
|
|
|
: requestInit;
|
|
|
|
|
|
|
|
const cacheHash = md5(JSON.stringify([url, requestParams, ...rest]) + bodyFunctionName);
|
|
|
|
const cachedFilePath = path.join(cacheDirPath, `${cacheHash}.json`);
|
|
|
|
|
|
|
|
try {
|
|
|
|
const rawResponse = JSON.parse(await fs.promises.readFile(cachedFilePath));
|
|
|
|
return new Response(rawResponse);
|
|
|
|
} catch (err) {
|
|
|
|
const fetchResponse = await fetch(...requestArguments);
|
|
|
|
const rawResponse = createRawResponse(fetchResponse);
|
|
|
|
await fs.promises.writeFile(cachedFilePath, JSON.stringify(rawResponse));
|
|
|
|
return new Response(rawResponse);
|
2020-04-17 20:31:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function createFetch(cacheDirPath) {
|
|
|
|
let madeDir = false;
|
|
|
|
|
|
|
|
return async (...args) => {
|
|
|
|
if (!madeDir) {
|
2020-11-28 02:46:49 +00:00
|
|
|
await fs.promises.mkdir(cacheDirPath, { recursive: true });
|
2020-04-17 20:31:22 +00:00
|
|
|
madeDir = true;
|
|
|
|
}
|
|
|
|
|
2020-11-28 02:46:49 +00:00
|
|
|
return getResponse(cacheDirPath, args);
|
2020-04-17 20:31:22 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = createFetch;
|