implement new expanded response caching logic
This commit is contained in:
parent
e6ac859d1c
commit
37daa38c7c
3
.gitignore
vendored
3
.gitignore
vendored
@ -102,3 +102,6 @@ dist
|
|||||||
|
|
||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
|
# Other
|
||||||
|
.cache
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
.eslintrc.js
|
.eslintrc.js
|
||||||
test
|
test
|
||||||
|
.cache
|
||||||
|
22
.vscode/launch.json
vendored
Normal file
22
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"args": [
|
||||||
|
"--colors",
|
||||||
|
"${workspaceFolder}/test"
|
||||||
|
],
|
||||||
|
"internalConsoleOptions": "openOnSessionStart",
|
||||||
|
"name": "Mocha Tests",
|
||||||
|
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
||||||
|
"request": "launch",
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**"
|
||||||
|
],
|
||||||
|
"type": "pwa-node"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
87
index.js
87
index.js
@ -7,9 +7,48 @@ function md5(str) {
|
|||||||
return crypto.createHash('md5').update(str).digest('hex');
|
return crypto.createHash('md5').update(str).digest('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getResponse(cacheDirPath, requestArguments, bodyFunctionName) {
|
class Response {
|
||||||
|
constructor(raw, cacheFilePath) {
|
||||||
|
Object.assign(this, raw);
|
||||||
|
this.cacheFilePath = cacheFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
text() {
|
||||||
|
return this.bodyBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
json() {
|
||||||
|
return JSON.parse(this.bodyBuffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer() {
|
||||||
|
return this.bodyBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 [url, requestInit, ...rest] = requestArguments;
|
||||||
const requestParams = requestInit && requestInit.body
|
const requestParams = requestInit.body
|
||||||
? ({ ...requestInit, body: typeof requestInit.body === 'object' ? requestInit.body.toString() : requestInit.body })
|
? ({ ...requestInit, body: typeof requestInit.body === 'object' ? requestInit.body.toString() : requestInit.body })
|
||||||
: requestInit;
|
: requestInit;
|
||||||
|
|
||||||
@ -17,40 +56,13 @@ async function getResponse(cacheDirPath, requestArguments, bodyFunctionName) {
|
|||||||
const cachedFilePath = path.join(cacheDirPath, `${cacheHash}.json`);
|
const cachedFilePath = path.join(cacheDirPath, `${cacheHash}.json`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const body = JSON.parse(await fs.promises.readFile(cachedFilePath));
|
const rawResponse = JSON.parse(await fs.promises.readFile(cachedFilePath));
|
||||||
if (bodyFunctionName === 'buffer') {
|
return new Response(rawResponse);
|
||||||
return Buffer.from(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
return body;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const fetchResponse = await fetch(...requestArguments);
|
const fetchResponse = await fetch(...requestArguments);
|
||||||
const bodyResponse = await fetchResponse[bodyFunctionName]();
|
const rawResponse = createRawResponse(fetchResponse);
|
||||||
await fs.promises.writeFile(cachedFilePath, JSON.stringify(bodyResponse));
|
await fs.promises.writeFile(cachedFilePath, JSON.stringify(rawResponse));
|
||||||
return bodyResponse;
|
return new Response(rawResponse);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ResponseWrapper {
|
|
||||||
constructor(cacheDirPath, requestArguments) {
|
|
||||||
this.cacheDirPath = cacheDirPath;
|
|
||||||
this.requestArguments = requestArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
text() {
|
|
||||||
return getResponse(this.cacheDirPath, this.requestArguments, this.text.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
json() {
|
|
||||||
return getResponse(this.cacheDirPath, this.requestArguments, this.json.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer() {
|
|
||||||
return getResponse(this.cacheDirPath, this.requestArguments, this.buffer.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
textConverted() {
|
|
||||||
return getResponse(this.cacheDirPath, this.requestArguments, this.textConverted.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,16 +71,11 @@ function createFetch(cacheDirPath) {
|
|||||||
|
|
||||||
return async (...args) => {
|
return async (...args) => {
|
||||||
if (!madeDir) {
|
if (!madeDir) {
|
||||||
try {
|
|
||||||
await fs.promises.mkdir(cacheDirPath, { recursive: true });
|
await fs.promises.mkdir(cacheDirPath, { recursive: true });
|
||||||
} catch (err) {
|
|
||||||
// Ignore.
|
|
||||||
}
|
|
||||||
|
|
||||||
madeDir = true;
|
madeDir = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ResponseWrapper(cacheDirPath, args);
|
return getResponse(cacheDirPath, args);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"description": "node-fetch with a persistent cache.",
|
"description": "node-fetch with a persistent cache.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "mocha",
|
||||||
"lint": "./node_modules/.bin/eslint .",
|
"lint": "./node_modules/.bin/eslint .",
|
||||||
"lintfix": "./node_modules/.bin/eslint . --fix"
|
"lintfix": "./node_modules/.bin/eslint . --fix"
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
const assert = require('assert');
|
||||||
|
const path = require('path');
|
||||||
|
const fetch = require('../index.js')(path.join(__dirname, '..', '.cache'));
|
||||||
|
|
||||||
|
const TWO_HUNDRED_URL = 'https://httpbin.org/status/200';
|
||||||
|
const FOUR_HUNDRED_URL = 'https://httpbin.org/status/400';
|
||||||
|
const THREE_HUNDRED_TWO_URL = 'https://httpbin.org/status/302';
|
||||||
|
|
||||||
|
describe('Basic property tests', function() {
|
||||||
|
it('Has a status property', async function() {
|
||||||
|
const res = await fetch(TWO_HUNDRED_URL);
|
||||||
|
assert.strictEqual(res.status, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has a statusText property', async function() {
|
||||||
|
const res = await fetch(TWO_HUNDRED_URL);
|
||||||
|
assert.strictEqual(res.statusText, 'OK');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has a type property', async function() {
|
||||||
|
const res = await fetch(TWO_HUNDRED_URL);
|
||||||
|
assert.strictEqual(res.type, 'basic');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has a url property', async function() {
|
||||||
|
const res = await fetch(TWO_HUNDRED_URL);
|
||||||
|
assert.strictEqual(res.url, TWO_HUNDRED_URL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has a useFinalURL property', async function() {
|
||||||
|
const res = await fetch(TWO_HUNDRED_URL);
|
||||||
|
assert.strictEqual(res.useFinalURL, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has an ok property', async function() {
|
||||||
|
const res = await fetch(FOUR_HUNDRED_URL);
|
||||||
|
assert.strictEqual(res.ok, false);
|
||||||
|
assert.strictEqual(res.status, 400);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has a headers property', async function() {
|
||||||
|
const res = await fetch(TWO_HUNDRED_URL);
|
||||||
|
assert.notStrictEqual(res.headers, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Has a redirected property', async function() {
|
||||||
|
const res = await fetch(THREE_HUNDRED_TWO_URL);
|
||||||
|
assert.strictEqual(res.redirected, true);
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user