forked from mirrored/github-readme-stats
feat: disable cache with proper headers when CACHE_SECONDS env is zero (#4539)
* feat: disable cache with proper headers when CACHE_SECONDS env is zero * Update src/common/cache.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Alexandr <qwerty541zxc@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot
Alexandr
parent
66764616fa
commit
e8e5cf86fb
+34
-3
@@ -15,13 +15,31 @@ import { clampValue, CONSTANTS } from "./utils.js";
|
||||
const resolveCacheSeconds = ({ requested, def, min, max }) => {
|
||||
let cacheSeconds = clampValue(isNaN(requested) ? def : requested, min, max);
|
||||
|
||||
cacheSeconds = process.env.CACHE_SECONDS
|
||||
? parseInt(process.env.CACHE_SECONDS, 10) || cacheSeconds
|
||||
: cacheSeconds;
|
||||
if (process.env.CACHE_SECONDS) {
|
||||
const envCacheSeconds = parseInt(process.env.CACHE_SECONDS, 10);
|
||||
if (!isNaN(envCacheSeconds)) {
|
||||
cacheSeconds = envCacheSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
return cacheSeconds;
|
||||
};
|
||||
|
||||
/**
|
||||
* Disables caching by setting appropriate headers on the response object.
|
||||
*
|
||||
* @param {Object} res The response object.
|
||||
*/
|
||||
const disableCaching = (res) => {
|
||||
// Disable caching for browsers, shared caches/CDNs, and GitHub Camo.
|
||||
res.setHeader(
|
||||
"Cache-Control",
|
||||
"no-cache, no-store, must-revalidate, max-age=0, s-maxage=0",
|
||||
);
|
||||
res.setHeader("Pragma", "no-cache");
|
||||
res.setHeader("Expires", "0");
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the Cache-Control headers on the response object.
|
||||
*
|
||||
@@ -29,6 +47,11 @@ const resolveCacheSeconds = ({ requested, def, min, max }) => {
|
||||
* @param {number} cacheSeconds The cache seconds to set in the headers.
|
||||
*/
|
||||
const setCacheHeaders = (res, cacheSeconds) => {
|
||||
if (cacheSeconds < 1) {
|
||||
disableCaching(res);
|
||||
return;
|
||||
}
|
||||
|
||||
res.setHeader(
|
||||
"Cache-Control",
|
||||
`max-age=${cacheSeconds}, ` +
|
||||
@@ -43,6 +66,14 @@ const setCacheHeaders = (res, cacheSeconds) => {
|
||||
* @param {Object} res The response object.
|
||||
*/
|
||||
const setErrorCacheHeaders = (res) => {
|
||||
const envCacheSeconds = process.env.CACHE_SECONDS
|
||||
? parseInt(process.env.CACHE_SECONDS, 10)
|
||||
: NaN;
|
||||
if (!isNaN(envCacheSeconds) && envCacheSeconds < 1) {
|
||||
disableCaching(res);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use lower cache period for errors.
|
||||
res.setHeader(
|
||||
"Cache-Control",
|
||||
|
||||
+37
-1
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
|
||||
import { jest } from "@jest/globals";
|
||||
import { beforeEach, jest } from "@jest/globals";
|
||||
import axios from "axios";
|
||||
import MockAdapter from "axios-mock-adapter";
|
||||
import api from "../api/index.js";
|
||||
@@ -99,6 +99,10 @@ const faker = (query, data) => {
|
||||
return { req, res };
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.CACHE_SECONDS = undefined;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.reset();
|
||||
});
|
||||
@@ -224,6 +228,38 @@ describe("Test /api/", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("should properly set cache using CACHE_SECONDS env variable", async () => {
|
||||
process.env.CACHE_SECONDS = "10000";
|
||||
|
||||
const { req, res } = faker({}, data_stats);
|
||||
await api(req, res);
|
||||
|
||||
expect(res.setHeader.mock.calls).toEqual([
|
||||
["Content-Type", "image/svg+xml"],
|
||||
[
|
||||
"Cache-Control",
|
||||
`max-age=10000, s-maxage=10000, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it("should disable cache when CACHE_SECONDS is set to 0", async () => {
|
||||
process.env.CACHE_SECONDS = "0";
|
||||
|
||||
const { req, res } = faker({}, data_stats);
|
||||
await api(req, res);
|
||||
|
||||
expect(res.setHeader.mock.calls).toEqual([
|
||||
["Content-Type", "image/svg+xml"],
|
||||
[
|
||||
"Cache-Control",
|
||||
"no-cache, no-store, must-revalidate, max-age=0, s-maxage=0",
|
||||
],
|
||||
["Pragma", "no-cache"],
|
||||
["Expires", "0"],
|
||||
]);
|
||||
});
|
||||
|
||||
it("should set proper cache with clamped values", async () => {
|
||||
{
|
||||
let { req, res } = faker({ cache_seconds: 200_000 }, data_stats);
|
||||
|
||||
Reference in New Issue
Block a user