Make redbean cache directive configurable (#750)

Thank you @johnmuhl for the proposal. Fixes #739
This commit is contained in:
Paul Kulchenko 2023-02-23 22:24:40 -08:00 committed by GitHub
parent db16f0129a
commit 0312898979
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 16 deletions

View file

@ -1419,15 +1419,18 @@ FUNCTIONS
listing page. The brand string needs to be a UTF-8 value that's listing page. The brand string needs to be a UTF-8 value that's
encodable as ISO-8859-1. If the brand is changed to something encodable as ISO-8859-1. If the brand is changed to something
other than redbean, then the promotional links will be removed other than redbean, then the promotional links will be removed
from the listing page too. This function should only be called from the listing page too.
from /.init.lua. This function should only be called from /.init.lua.
ProgramCache(seconds:int) ProgramCache(seconds:int[, directive:string])
Configures Cache-Control and Expires header generation for static Configures Cache-Control and Expires header generation for static
asset serving. A negative value will disable the headers. Zero asset serving. A negative value will disable the headers. Zero
means don't cache. Greater than zero asks public proxies and means don't cache. Greater than zero asks public proxies and
browsers to cache for a given number of seconds. This should only browsers to cache for a given number of seconds. The directive
be called from /.init.lua. value is added to the Cache-Control header when specified (with
"must-revalidate" provided by default) and can be set to an empty
string to remove the default value.
This function should only be called from /.init.lua.
ProgramCertificate(pem:str) ProgramCertificate(pem:str)
Same as the -C flag if called from .init.lua, e.g. Same as the -C flag if called from .init.lua, e.g.
@ -1458,7 +1461,7 @@ FUNCTIONS
ProgramTimeout(milliseconds:int|seconds:int) ProgramTimeout(milliseconds:int|seconds:int)
Default timeout is 60000ms. Minimal value of timeout is 10(ms). Default timeout is 60000ms. Minimal value of timeout is 10(ms).
Negative values (<0) sets the keepalive in seconds. Negative values (<0) sets the keepalive in seconds.
This should only be called from /.init.lua. This function should only be called from /.init.lua.
ProgramPort(uint16) ProgramPort(uint16)
Hard-codes the port number on which to listen, which can be any Hard-codes the port number on which to listen, which can be any
@ -1496,8 +1499,8 @@ FUNCTIONS
Configures fallback routing for paths which would otherwise return Configures fallback routing for paths which would otherwise return
404 Not Found. If code is 0 then the path is rewritten internally 404 Not Found. If code is 0 then the path is rewritten internally
as an accelerated redirect. If code is 301, 302, 307, or 308 then as an accelerated redirect. If code is 301, 302, 307, or 308 then
a redirect response will be sent to the client. This should only a redirect response will be sent to the client.
be called from /.init.lua. This function should only be called from /.init.lua.
ProgramSslTicketLifetime(seconds:int) ProgramSslTicketLifetime(seconds:int)
Defaults to 86400 (24 hours). This may be set to ≤0 to disable Defaults to 86400 (24 hours). This may be set to ≤0 to disable

View file

@ -498,6 +498,7 @@ static const char *histpath;
static struct pollfd *polls; static struct pollfd *polls;
static size_t payloadlength; static size_t payloadlength;
static int64_t cacheseconds; static int64_t cacheseconds;
static const char *cachedirective;
static const char *monitortty; static const char *monitortty;
static const char *serverheader; static const char *serverheader;
static struct Strings stagedirs; static struct Strings stagedirs;
@ -1037,8 +1038,9 @@ static void ProgramTimeout(long ms) {
} }
} }
static void ProgramCache(long x) { static void ProgramCache(long x, const char *s) {
cacheseconds = x; cacheseconds = x;
if (s) cachedirective = s;
} }
static void SetDefaults(void) { static void SetDefaults(void) {
@ -1046,7 +1048,7 @@ static void SetDefaults(void) {
VERSION >> 010, VERSION >> 000))); VERSION >> 010, VERSION >> 000)));
__log_level = kLogInfo; __log_level = kLogInfo;
maxpayloadsize = 64 * 1024; maxpayloadsize = 64 * 1024;
ProgramCache(-1); ProgramCache(-1, "must-revalidate");
ProgramTimeout(60 * 1000); ProgramTimeout(60 * 1000);
ProgramSslTicketLifetime(24 * 60 * 60); ProgramSslTicketLifetime(24 * 60 * 60);
sslfetchverify = true; sslfetchverify = true;
@ -2275,14 +2277,15 @@ static char *AppendExpires(char *p, int64_t t) {
return AppendCrlf(p); return AppendCrlf(p);
} }
static char *AppendCache(char *p, int64_t seconds) { static char *AppendCache(char *p, int64_t seconds, char *directive) {
if (seconds < 0) return p; if (seconds < 0) return p;
p = stpcpy(p, "Cache-Control: max-age="); p = stpcpy(p, "Cache-Control: max-age=");
p = FormatUint64(p, seconds); p = FormatUint64(p, seconds);
if (!seconds) { if (!seconds) {
p = stpcpy(p, ", no-store"); p = stpcpy(p, ", no-store");
} else { } else if (directive && *directive) {
p = stpcpy(p, ", must-revalidate"); p = stpcpy(p, ", ");
p = stpcpy(p, directive);
} }
p = AppendCrlf(p); p = AppendCrlf(p);
return AppendExpires(p, shared->nowish.tv_sec + seconds); return AppendExpires(p, shared->nowish.tv_sec + seconds);
@ -4442,7 +4445,8 @@ static int LuaProgramPort(lua_State *L) {
static int LuaProgramCache(lua_State *L) { static int LuaProgramCache(lua_State *L) {
OnlyCallFromMainProcess(L, "ProgramCache"); OnlyCallFromMainProcess(L, "ProgramCache");
return LuaProgramInt(L, ProgramCache); ProgramCache(luaL_checkinteger(L, 1), luaL_optstring(L, 2, NULL));
return 0;
} }
static int LuaProgramTimeout(lua_State *L) { static int LuaProgramTimeout(lua_State *L) {
@ -6159,7 +6163,7 @@ static char *ServeAsset(struct Asset *a, const char *path, size_t pathlen) {
p = AppendHeader(p, "Last-Modified", a->lastmodifiedstr); p = AppendHeader(p, "Last-Modified", a->lastmodifiedstr);
if (cpm.msg.version >= 11) { if (cpm.msg.version >= 11) {
if (!cpm.gotcachecontrol) { if (!cpm.gotcachecontrol) {
p = AppendCache(p, cacheseconds); p = AppendCache(p, cacheseconds, cachedirective);
} }
if (!IsCompressed(a)) { if (!IsCompressed(a)) {
p = stpcpy(p, "Accept-Ranges: bytes\r\n"); p = stpcpy(p, "Accept-Ranges: bytes\r\n");
@ -7279,7 +7283,11 @@ static void GetOpts(int argc, char *argv[]) {
CASE('G', ProgramGid(atoi(optarg))); CASE('G', ProgramGid(atoi(optarg)));
CASE('p', ProgramPort(ParseInt(optarg))); CASE('p', ProgramPort(ParseInt(optarg)));
CASE('R', ProgramRedirectArg(0, optarg)); CASE('R', ProgramRedirectArg(0, optarg));
CASE('c', ProgramCache(ParseInt(optarg))); case 'c': ; // accept "num" or "num,directive"
char *p;
long ret = strtol(optarg, &p, 0);
ProgramCache(ret, *p ? p+1 : NULL); // skip separator, if any
break;
CASE('r', ProgramRedirectArg(307, optarg)); CASE('r', ProgramRedirectArg(307, optarg));
CASE('t', ProgramTimeout(ParseInt(optarg))); CASE('t', ProgramTimeout(ParseInt(optarg)));
CASE('h', PrintUsage(1, EXIT_SUCCESS)); CASE('h', PrintUsage(1, EXIT_SUCCESS));