Description: Normalize absolute-form requests with an empty path (VSV00018)
 .
 Backport to 7.7: retain http_method_eq and the stable method API.
 Adapt the upstream r01255 cases without newer logging/counter assertions;
 use pass to avoid cached responses masking individual parser outcomes.
Author: Nils Goroll <nils.goroll@uplex.de>
Origin: https://code.vinyl-cache.org/vinyl-cache/vinyl-cache/commit/73dcb85eb8ad9fa9b462c5477d8c4b5061f615de
Bug: https://vinyl-cache.org/security/VSV00018.html
Forwarded: not-needed
Last-Update: 2026-10-23

--- a/bin/varnishd/http1/cache_http1_proto.c
+++ b/bin/varnishd/http1/cache_http1_proto.c
@@ -375,10 +375,16 @@
 		b = hp->hd[HTTP_HDR_URL].b + 8;
 	if (b) {
 		e = strchr(b, '/');
-		if (e) {
-			http_Unset(hp, H_Host);
-			http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b);
-			hp->hd[HTTP_HDR_URL].b = e;
+		if (e == NULL)
+			e = hp->hd[HTTP_HDR_URL].e;
+		http_Unset(hp, H_Host);
+		http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b);
+		hp->hd[HTTP_HDR_URL].b = e;
+		if (Tlen(hp->hd[HTTP_HDR_URL]) == 0) {
+			if (http_method_eq(http_GetMethod(hp), OPTIONS))
+				hp->hd[HTTP_HDR_URL] = Tstr("*");
+			else
+				hp->hd[HTTP_HDR_URL] = Tstr("/");
 		}
 	}
 
--- a/bin/varnishtest/tests/r01255.vtc
+++ b/bin/varnishtest/tests/r01255.vtc
@@ -1,19 +1,46 @@
-varnishtest "Test RFC2616 5.2 compliance"
+varnishtest "Test RFC9112 3.2 compliance"
 
-server s1 {
+server s1 -repeat 6 {
 	rxreq
 	txresp -hdr "Foo: 1"
 } -start
 
 varnish v1 -vcl+backend {
-
+	sub vcl_recv { return (pass); }
 	sub vcl_deliver {
 		set resp.http.rxhost = req.http.host;
+		set resp.http.url = req.url;
 	}
 } -start
 
 client c1 {
-	txreq -url http://www.example.com/bar
+	txreq -url http://www.example.com/bar -hdr "host: another"
 	rxresp
 	expect resp.http.rxhost == www.example.com
+	expect resp.http.url == /bar
+
+	txreq -url http://www.example.com/ -hdr "host: another"
+	rxresp
+	expect resp.http.rxhost == www.example.com
+	expect resp.http.url == /
+
+	txreq -url http://www.example.com -hdr "host: another"
+	rxresp
+	expect resp.http.rxhost == www.example.com
+	expect resp.http.url == /
+
+	txreq -method OPTIONS -url http://www.example.com -hdr "host: another"
+	rxresp
+	expect resp.http.rxhost == www.example.com
+	expect resp.http.url == *
+
+	txreq -url http:///bar -hdr "host: another"
+	rxresp
+	expect resp.http.rxhost == ""
+	expect resp.http.url == /bar
+
+	txreq -url http:// -hdr "host: another"
+	rxresp
+	expect resp.http.rxhost == ""
+	expect resp.http.url == /
 } -run
