[PATCH 2/2] ttl: Support different TTL times based on cache-control

Tim Nordell tim.nordell at logicpd.com
Fri Feb 26 21:57:09 CET 2016


Allow the client browser to pass in "max-age=0" and "no-cache"
to control a separate TTL time on the server for each type of
page.  This extends the TTL field to have the additional form
of:

    some-ttl=5:1

where 5 is the number of minutes if the user were to simply
load the page, and 1 is the number of minutes if the user were
to reload the page in their web browser (hit refresh).

Signed-off-by: Tim Nordell <tim.nordell at logicpd.com>

diff --git a/cgit.c b/cgit.c
index 963aee8..0ca1baa 100644
--- a/cgit.c
+++ b/cgit.c
@@ -29,6 +29,30 @@ static void add_mimetype(const char *name, const char *value)
 
 static void process_cached_repolist(const char *path);
 
+/**
+ * \brief Convert TTL field into a TTL structure
+ *
+ * \param value Value from field; should be one of the following forms:
+ *                      [normal]
+ *                      [normal]:[forced]
+ * \return Parsed TTL value
+ */
+static struct cgit_ttl ttl_value(const char *value)
+{
+	char *param2;
+	struct cgit_ttl ret;
+
+	ret.normal = atoi(value);
+
+	param2 = strchr(value, ':');
+	if(NULL != param2)
+		ret.forced = atoi(&param2[1]);
+	else
+		ret.forced = -1;
+
+	return ret;
+}
+
 static void repo_config(struct cgit_repo *repo, const char *name, const char *value)
 {
 	struct string_list_item *item;
@@ -187,19 +211,19 @@ static void config_cb(const char *name, const char *value)
 	else if (!strcmp(name, "cache-root"))
 		ctx.cfg.cache_root = xstrdup(expand_macros(value));
 	else if (!strcmp(name, "cache-root-ttl"))
-		ctx.cfg.cache_root_ttl = atoi(value);
+		ctx.cfg.cache_root_ttl = ttl_value(value);
 	else if (!strcmp(name, "cache-repo-ttl"))
-		ctx.cfg.cache_repo_ttl = atoi(value);
+		ctx.cfg.cache_repo_ttl = ttl_value(value);
 	else if (!strcmp(name, "cache-scanrc-ttl"))
 		ctx.cfg.cache_scanrc_ttl = atoi(value);
 	else if (!strcmp(name, "cache-static-ttl"))
-		ctx.cfg.cache_static_ttl = atoi(value);
+		ctx.cfg.cache_static_ttl = ttl_value(value);
 	else if (!strcmp(name, "cache-dynamic-ttl"))
-		ctx.cfg.cache_dynamic_ttl = atoi(value);
+		ctx.cfg.cache_dynamic_ttl = ttl_value(value);
 	else if (!strcmp(name, "cache-about-ttl"))
-		ctx.cfg.cache_about_ttl = atoi(value);
+		ctx.cfg.cache_about_ttl = ttl_value(value);
 	else if (!strcmp(name, "cache-snapshot-ttl"))
-		ctx.cfg.cache_snapshot_ttl = atoi(value);
+		ctx.cfg.cache_snapshot_ttl = ttl_value(value);
 	else if (!strcmp(name, "case-sensitive-sort"))
 		ctx.cfg.case_sensitive_sort = atoi(value);
 	else if (!strcmp(name, "about-filter"))
@@ -352,13 +376,19 @@ static void prepare_context(void)
 	ctx.cfg.cache_size = 0;
 	ctx.cfg.cache_max_create_time = 5;
 	ctx.cfg.cache_root = CGIT_CACHE_ROOT;
-	ctx.cfg.cache_about_ttl = 15;
-	ctx.cfg.cache_snapshot_ttl = 5;
-	ctx.cfg.cache_repo_ttl = 5;
-	ctx.cfg.cache_root_ttl = 5;
+	ctx.cfg.cache_about_ttl.normal = 15;
+	ctx.cfg.cache_about_ttl.forced = -1;
+	ctx.cfg.cache_snapshot_ttl.normal = 5;
+	ctx.cfg.cache_snapshot_ttl.forced = -1;
+	ctx.cfg.cache_repo_ttl.normal = 5;
+	ctx.cfg.cache_repo_ttl.forced = -1;
+	ctx.cfg.cache_root_ttl.normal = 5;
+	ctx.cfg.cache_root_ttl.forced = -1;
 	ctx.cfg.cache_scanrc_ttl = 15;
-	ctx.cfg.cache_dynamic_ttl = 5;
-	ctx.cfg.cache_static_ttl = -1;
+	ctx.cfg.cache_dynamic_ttl.normal = 5;
+	ctx.cfg.cache_dynamic_ttl.forced = -1;
+	ctx.cfg.cache_static_ttl.normal = -1;
+	ctx.cfg.cache_static_ttl.forced = -1;
 	ctx.cfg.case_sensitive_sort = 1;
 	ctx.cfg.branch_sort = 0;
 	ctx.cfg.commit_sort = 0;
@@ -405,6 +435,7 @@ static void prepare_context(void)
 	ctx.env.server_port = getenv("SERVER_PORT");
 	ctx.env.http_cookie = getenv("HTTP_COOKIE");
 	ctx.env.http_referer = getenv("HTTP_REFERER");
+	ctx.env.http_cache_control = getenv("HTTP_CACHE_CONTROL");
 	ctx.env.content_length = getenv("CONTENT_LENGTH") ? strtoul(getenv("CONTENT_LENGTH"), NULL, 10) : 0;
 	ctx.env.authenticated = 0;
 	ctx.page.mimetype = "text/html";
@@ -1006,7 +1037,7 @@ static void cgit_parse_args(int argc, const char **argv)
 static int calc_ttl(void)
 {
 	const int ttl_conversion_multiplier = 60;
-	int ttl;
+	struct cgit_ttl ttl;
 
 	if (!ctx.repo)
 		ttl = ctx.cfg.cache_root_ttl;
@@ -1023,8 +1054,14 @@ static int calc_ttl(void)
 	else
 		ttl = ctx.cfg.cache_repo_ttl;
 
-	if (ttl >= 0)
-		return ttl * ttl_conversion_multiplier;
+	if(ttl.forced >= 0 && NULL != ctx.env.http_cache_control &&
+	    (!strcmp(ctx.env.http_cache_control, "max-age=0") ||
+	     !strcmp(ctx.env.http_cache_control, "no-cache"))
+	  )
+		return ttl.forced * ttl_conversion_multiplier;
+
+	if (ttl.normal >= 0)
+		return ttl.normal * ttl_conversion_multiplier;
 
 	return 10 * 365 * 24 * 60 * 60; /* 10 years */
 }
diff --git a/cgit.h b/cgit.h
index 325432b..350d25d 100644
--- a/cgit.h
+++ b/cgit.h
@@ -185,6 +185,11 @@ struct cgit_query {
 	char *vpath;
 };
 
+struct cgit_ttl {
+	int normal;
+	int forced;
+};
+
 struct cgit_config {
 	char *agefile;
 	char *cache_root;
@@ -213,14 +218,14 @@ struct cgit_config {
 	char *virtual_root;	/* Always ends with '/'. */
 	char *strict_export;
 	int cache_size;
-	int cache_dynamic_ttl;
 	int cache_max_create_time;
-	int cache_repo_ttl;
-	int cache_root_ttl;
 	int cache_scanrc_ttl;
-	int cache_static_ttl;
-	int cache_about_ttl;
-	int cache_snapshot_ttl;
+	struct cgit_ttl cache_root_ttl;
+	struct cgit_ttl cache_repo_ttl;
+	struct cgit_ttl cache_about_ttl;
+	struct cgit_ttl cache_static_ttl;
+	struct cgit_ttl cache_dynamic_ttl;
+	struct cgit_ttl cache_snapshot_ttl;
 	int case_sensitive_sort;
 	int embedded;
 	int enable_filter_overrides;
@@ -295,6 +300,7 @@ struct cgit_environment {
 	const char *server_port;
 	const char *http_cookie;
 	const char *http_referer;
+	const char *http_cache_control;
 	unsigned int content_length;
 	int authenticated;
 };
diff --git a/ui-shared.c b/ui-shared.c
index 9a38aa9..2ab2fd9 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -789,7 +789,7 @@ void cgit_print_docend(void)
 void cgit_print_error_page(int code, const char *msg, const char *fmt, ...)
 {
 	va_list ap;
-	ctx.page.expires = ctx.cfg.cache_dynamic_ttl;
+	ctx.page.expires = ctx.cfg.cache_dynamic_ttl.normal;
 	ctx.page.status = code;
 	ctx.page.statusmsg = msg;
 	cgit_print_http_headers();
-- 
2.4.9



More information about the CGit mailing list