Skip to content

Commit

Permalink
fix(core-api): cache status code and headers (#4329)
Browse files Browse the repository at this point in the history
  • Loading branch information
rainydio authored Feb 25, 2021
1 parent fa98820 commit 00f479a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 20 deletions.
6 changes: 2 additions & 4 deletions __tests__/unit/core-api/service-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,7 @@ describe("ServiceProvider", () => {
// @ts-ignore
defaults.customField = "dummy";

const result = (coreApiServiceProvider.configSchema() as AnySchema).validate(
defaults
);
const result = (coreApiServiceProvider.configSchema() as AnySchema).validate(defaults);

expect(result.error).toBeUndefined();
expect(result.value.customField).toEqual("dummy");
Expand Down Expand Up @@ -346,7 +344,7 @@ describe("ServiceProvider", () => {
expect(result.value.plugins.cache.enabled).toEqual(false);
});

it("should return true if process.env.CORE_API_CACHE_DISABLED is defined", async () => {
it("should return true if process.env.CORE_API_CACHE is defined", async () => {
process.env.CORE_API_CACHE = "true";

jest.resetModules();
Expand Down
58 changes: 42 additions & 16 deletions packages/core-api/src/plugins/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { Crypto } from "@arkecosystem/crypto";
import Hapi from "@hapi/hapi";
import NodeCache from "node-cache";

type CachedResponse = {
code: number;
headers: Record<string, string | string[]>;
payload: unknown;
};

const generateCacheKey = (request: Hapi.Request): string =>
Crypto.HashAlgorithms.sha256(
JSON.stringify({
Expand Down Expand Up @@ -34,22 +40,19 @@ export = {
type: "onPreHandler",
async method(request: Hapi.Request, h: Hapi.ResponseToolkit) {
const cacheKey: string = generateCacheKey(request);
const cachedResponse: CachedResponse | undefined = cache.get(cacheKey);

if (cache.has(cacheKey)) {
const value: { isBoom: boolean; data: Record<string, any> } | undefined = cache.get(cacheKey);

if (value === undefined || value === null) {
return h.continue;
}
if (cachedResponse) {
const newResponse = h.response(cachedResponse.payload).code(cachedResponse.code);

if (value.isBoom) {
return h.response(value.data.payload).code(value.data.statusCode).takeover();
for (const [headerName, headerValue] of Object.entries(cachedResponse.headers)) {
newResponse.header(headerName, headerValue);
}

return h.response(value.data).code(200).takeover();
return newResponse.takeover();
} else {
return h.continue;
}

return h.continue;
},
});

Expand All @@ -58,13 +61,36 @@ export = {
async method(request: Hapi.Request, h: Hapi.ResponseToolkit) {
const cacheKey: string = generateCacheKey(request);

if (!cache.has(cacheKey)) {
cache.set(cacheKey, {
isBoom: request.response.isBoom === true,
data: request.response.isBoom ? request.response.output : request.response.source,
});
let code: number;
let headers: Record<string, string | string[]>;
let payload: unknown;

if (request.response.isBoom) {
code = request.response.output.statusCode;
headers = request.response.output.headers;
payload = request.response.output.payload;
} else {
code = request.response.statusCode;
headers = request.response.headers;
payload = request.response.source;
}

const cachedResponse: CachedResponse = {
code,
headers: {},
payload,
};

if (code >= 300 && code < 400 && "location" in headers) {
cachedResponse.headers["location"] = headers["location"];
}

if ("content-type" in headers) {
cachedResponse["content-type"] = headers["content-type"];
}

cache.set(cacheKey, cachedResponse);

return h.continue;
},
});
Expand Down

0 comments on commit 00f479a

Please sign in to comment.