[v2,1/1] support http header 'Cache-Control: no-cache' for soft failure

Message ID 20220929140759.59575-1-list@eworm.de
State Under Review
Headers show
Series [v2,1/1] support http header 'Cache-Control: no-cache' for soft failure | expand

Commit Message

Christian Hesse Sept. 29, 2022, 2:07 p.m. UTC
From: Christian Hesse <mail@eworm.de>

The idea has been borrowed from cloud providers' reverse proxies and
load balancers. These accept http headers to control caching behaviour,
even to control 'negative caching' when error codes are returned.

By setting the http header 'Cache-Control: no-cache' when returning with
the status code 404 (not found) the server can indicate that this is a
soft failure. No error message is shown, and server's error count is
not increased.

This can be used by servers that are not expected to be complete, for
example when serving a local cache [0]. In nginx this can be achived by
acting on error_page and sending the extra header by adding a directive:

    server {
        listen 8080 default_server;
        root /var/cache/pacman/pkg;
        error_page 404 = @no-cache;
        location @no-cache {
            add_header Cache-Control "no-cache" always;
        }
    }

Also this is a perfect match for pacredir [1].

[0] https://wiki.archlinux.org/title/Pacman/Tips_and_tricks#Network_shared_pacman_cache
[1] https://git.eworm.de/cgit/pacredir/about/

Signed-off-by: Christian Hesse <mail@eworm.de>
---
 lib/libalpm/dload.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

Patch

diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 4fa17b35..74462bba 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -274,8 +274,10 @@  static size_t dload_parseheader_cb(void *ptr, size_t size, size_t nmemb, void *u
 {
 	size_t realsize = size * nmemb;
 	const char *fptr, *endptr = NULL;
+	const char * const cc_header = "Cache-Control:";
 	const char * const cd_header = "Content-Disposition:";
 	const char * const fn_key = "filename=";
+	const char * const nc_key = "no-cache";
 	struct dload_payload *payload = (struct dload_payload *)user;
 	long respcode;
 
@@ -302,6 +304,15 @@  static size_t dload_parseheader_cb(void *ptr, size_t size, size_t nmemb, void *u
 		}
 	}
 
+	/* By setting the http header 'Cache-Control: no-cache' the server can indicate
+	   that this is a soft failure which should not be cached. No error message is
+	   shown, and server's error count is not increased. */
+	if(_alpm_raw_ncmp(cc_header, ptr, strlen(cc_header)) == 0) {
+		if(strstr(ptr, nc_key)) {
+			payload->errors_ok = 1;
+		}
+	}
+
 	curl_easy_getinfo(payload->curl, CURLINFO_RESPONSE_CODE, &respcode);
 	if(payload->respcode != respcode) {
 		payload->respcode = respcode;