[master] 39a9dae89 Add std.rfc_ttl()

Nils Goroll nils.goroll at uplex.de
Fri Dec 19 14:03:02 UTC 2025


commit 39a9dae89d6b1069dcb2dd731f130f2276e2f085
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Wed Dec 10 17:48:22 2025 +0100

    Add std.rfc_ttl()
    
    From the added documentation:
    
    Re-calculate the object timers (``beresp.ttl``, ``beresp.grace`` and
    ``beresp.keep``) based on the current state of ``beresp`` as if it had been
    processed by core code before ``vcl_backend_response`` was called. This does not
    change ``beresp.uncacheable``.
    
    This is useful to get the default ttl calculations after modifications of
    relevant properties like ``beresp.status``, ``beresp.http.Date``,
    ``beresp.http.Age`` or ``beresp.http.Cache-Control``.
    
    Documentation details polished by SashankBhamidi, thank you.

diff --git a/vmod/tests/std_b00015.vtc b/vmod/tests/std_b00015.vtc
new file mode 100644
index 000000000..d2004e101
--- /dev/null
+++ b/vmod/tests/std_b00015.vtc
@@ -0,0 +1,87 @@
+varnishtest "std.rfc_ttl()"
+
+server s1 {
+	rxreq
+	txresp -status 202 -hdr "Cache-Control: public, s-maxage=4711"
+
+	rxreq
+	expect req.url == "/200"
+	txresp -status 200 \
+	       -hdr "Cache-Control: public, s-maxage=0, stale-while-revalidate=99" \
+	       -hdr {Etag: "foo"} \
+	       -bodylen 64
+
+	rxreq
+	expect req.url == "/200"
+	expect req.http.If-None-Match == {"foo"}
+	txresp -status 304 -hdr "Cache-Control: s-maxage=11, stale-while-revalidate=77"
+} -start
+
+varnish v1 -vcl+backend {
+	import std;
+
+	sub vcl_backend_refresh {
+		set beresp.http.Cache-Control = "s-maxage=10, stale-while-revalidate=42";
+		std.rfc_ttl();
+	}
+
+	sub vcl_backend_response {
+		if (beresp.status == 202) {
+			set beresp.status = 200;
+			std.rfc_ttl();
+			set beresp.status = 202;
+		}
+		# avoid zero ttl which is uncacheable
+		set beresp.ttl += 0.001s;
+	}
+} -start
+
+logexpect l1 -v v1 -g vxid -q "vxid == 1002" {
+	fail add *	Error
+	fail add *	VCL_Error
+	fail add *	End
+	expect * 1002	TTL		{^RFC -1 }
+	expect 1 =	BerespStatus	{^200}
+	expect 1 =	TTL		{^RFC 4711 }
+	fail clear
+} -start
+
+logexpect l2 -v v1 -g vxid -q "vxid == 1004" {
+	fail add *	Error
+	fail add *	VCL_Error
+	fail add *	End
+	expect * 1004	BereqURL	{^/200}
+	expect * =	BerespStatus	{^200}
+	expect * =	TTL		{^RFC 0 99 }
+	fail clear
+} -start
+
+logexpect l3 -v v1 -g vxid -q "vxid == 1006" {
+	fail add *	Error
+	fail add *	VCL_Error
+	fail add *	End
+	expect * 1006	BereqURL	{^/200}
+	expect * =	BerespStatus	{^304}
+	expect * =	TTL		{^RFC 11 77 }
+	expect * =	TTL		{^RFC 10 42 }
+	fail clear
+} -start
+
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 202
+
+	txreq -url "/200"
+	rxresp
+	expect resp.status == 200
+
+	txreq -url "/200"
+	rxresp
+	expect resp.status == 200
+} -run
+
+logexpect l1 -wait
+logexpect l2 -wait
+logexpect l3 -wait
diff --git a/vmod/vmod_std.c b/vmod/vmod_std.c
index b2c9566b7..fc0f4d62c 100644
--- a/vmod/vmod_std.c
+++ b/vmod/vmod_std.c
@@ -385,3 +385,23 @@ vmod_timed_call(VRT_CTX, VCL_SUB sub)
 	VRT_call(ctx, sub);
 	return (VTIM_mono() - b);
 }
+
+VCL_VOID v_matchproto_(td_std_rfc_ttl)
+vmod_rfc_ttl(VRT_CTX)
+{
+	struct busyobj *bo;
+	struct objcore *oc;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	// $Restrict guarantees
+	bo = ctx->bo;
+	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
+	oc = bo->fetch_objcore;
+	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+
+	RFC2616_Ttl(bo, ctx->now,
+	     &oc->t_origin,
+	     &oc->ttl,
+	     &oc->grace,
+	     &oc->keep);
+}
diff --git a/vmod/vmod_std.vcc b/vmod/vmod_std.vcc
index 87978f615..25593c9bb 100644
--- a/vmod/vmod_std.vcc
+++ b/vmod/vmod_std.vcc
@@ -696,6 +696,19 @@ $Function DURATION timed_call(SUB)
 Call the given SUB and return a high precision measurement of the
 execution time.
 
+$Function VOID rfc_ttl()
+
+$Restrict vcl_backend_response vcl_backend_refresh
+
+Re-calculate the object timers (``beresp.ttl``, ``beresp.grace`` and
+``beresp.keep``) based on the current state of ``beresp`` as if it had been
+processed by core code before ``vcl_backend_response`` was called. This does not
+change ``beresp.uncacheable``.
+
+This is useful to get the default ttl calculations after modifications of
+relevant properties like ``beresp.status``, ``beresp.http.Date``,
+``beresp.http.Age`` or ``beresp.http.Cache-Control``.
+
 SEE ALSO
 ========
 



More information about the varnish-commit mailing list