vtest "Test dynamic backends"

# the use case for via-proxy is to have a(n ha)proxy make a(n ssl)
# connection on our behalf. For the purpose of testing, we use another
# vinyl in place - but we are behaving realistically in that we do
# not use any prior information for the actual backend connection -
# just the information from the proxy protocol

vinyl v2 -proto PROXY -vcl {
	import debug;
	import std;
	import proxy;

	backend dummy { .host = "${bad_backend}"; }

	sub vcl_init {
		new s1 = debug.dyn("0.0.0.0", "0");
	}

	sub vcl_recv {
		s1.refresh(server.ip, std.port(server.ip));
		set req.backend_hint = s1.backend();
		set req.http.Authority = proxy.authority();
		return (pass);
	}

	sub vcl_deliver {
		set resp.http.Authority = req.http.Authority;
	}
} -start


# NB: ${v2_addr} in s1's work should really be ${s1_addr}, but it is not
#     defined until after the (implicit) listen(2) call, so we cheat
#     and use v2's address instead.

server s1 {
	rxreq
	expect req.url == "/"
	expect req.http.Probe == "p1"
	expect req.http.Authority == <undef>
	txresp
	close
	accept
	rxreq
	expect req.url == "/1"
	expect req.http.Probe == <undef>
	expect req.http.Authority == <undef>
	txresp
	close
	accept
	rxreq
	expect req.url == "/"
	expect req.http.Probe == "p2"
	expect req.http.Authority == "${v2_addr}"
	txresp
	close
	accept
	rxreq
	expect req.url == "/2"
	expect req.http.Probe == <undef>
	expect req.http.Authority == "${v2_addr}"
	txresp
} -start

#
# we vtc.sleep to make sure that the health check is done and server
# s1 has accepted again. We would rather want to use barriers, but
# there is a (yet not understood) bug in vinyltest which prevents
# the bX_sock macros from being available in the second vinyl
# instance

vinyl v1 -vcl {
	import debug;
	import vtc;

	backend dummy { .host = "${bad_backend}"; }

	probe p1 {
		.threshold = 8;
		.initial = 8;
		.interval = 1m;
		.request =
			"GET / HTTP/1.1"
			"Host: ${s1_addr}"
			"Probe: p1"
			"Connection: close";
	}

	probe p2 {
		.threshold = 8;
		.initial = 8;
		.interval = 1m;
		.request =
			"GET / HTTP/1.1"
			"Host: ${s1_addr}"
			"Probe: p2"
			"Connection: close";
	}

	backend v2 { .host = "${v2_addr}"; .port = "${v2_port}"; }

	sub vcl_init {
		new s1 = debug.dyn("0.0.0.0", "0");
	}

	sub vcl_recv {
		if (req.url == "/1") {
			s1.refresh("${s1_addr}", "${s1_port}", p1);
			vtc.sleep(1s);
		} else if (req.url == "/2") {
			s1.refresh("${s1_addr}", "${s1_port}", p2,
			    via=v2);
			vtc.sleep(1s);
		}
		set req.backend_hint = s1.backend();
	}
} -start

vinyl v1 -expect MAIN.n_backend == 3

client c1 {
	txreq -url /1
	rxresp
	expect resp.status == 200
	expect resp.http.Authority == <undef>
	txreq -url /2
	rxresp
	expect resp.status == 200
	expect resp.http.Authority == "${s1_addr}"
} -run
