vtest "Test vcl_backend_refresh"

barrier b1 sock 2
barrier b2 sock 2

server s1 {
	rxreq
	txresp -hdr "Etag: abcd" -hdr "from-be: true" -body "abcdefghij"

	rxreq
	expect req.http.if-none-match == "abcd"
	txresp -status 304 -hdr "be304-1: true"

	rxreq
	expect req.http.if-none-match == "abcd"
	txresp -status 304 -hdr "be304-2: true"

	rxreq
	expect req.http.if-none-match == "abcd"
	txresp -status 304 -hdr "be304-3: true"

} -start

vinyl v1 -vcl+backend {

	sub vcl_backend_response {
		set beresp.ttl = 1ms;
		set beresp.grace = 0s;
		set beresp.keep = 10m;
		set beresp.http.was-304 = beresp.was_304;
	}

	sub vcl_backend_refresh {
		if (bereq.http.stale) {
			return (obj_stale);
		} else if (bereq.http.beresp) {
			return (beresp);
		}
	}

} -start

# insert object in cache
client c1 {
	txreq
	rxresp
	expect resp.status == 200
	expect resp.http.was-304 == false
	expect resp.http.from-be == true
	expect resp.bodylen == 10
	expect resp.body == "abcdefghij"
} -run

# let the object die
delay 0.01

# should get the stale obj headers only
client c2 {
	txreq -hdr "stale: 1"
	rxresp
	expect resp.status == 200
	expect resp.http.be304-1 == <undef>
	expect resp.http.from-be == true
	expect resp.bodylen == 10
	expect resp.body == "abcdefghij"
} -run

# let the object die
delay 0.01

# get the beresp headers only
client c3 {
	txreq -hdr "beresp: 1"
	rxresp
	expect resp.status == 200
	expect resp.http.from-bo == <undef>
	expect resp.http.be304-2 == true
	expect resp.bodylen == 10
	expect resp.body == "abcdefghij"
} -run

# let the object die
delay 0.01

# default, get a merge of stale_oc and beresp headers
client c4 {
	txreq
	rxresp
	expect resp.status == 200
	expect resp.http.from-bo == <undef>
	expect resp.http.be304-2 == true
	expect resp.http.be304-3 == true
	expect resp.bodylen == 10
	expect resp.body == "abcdefghij"
} -run

###################################################################

server s1 {
	rxreq
	expect req.http.if-none-match == "abcd"
	txresp -status 304 -hdr "be304-4: true"
} -start

vinyl v1 -vcl+backend {

	import vtc;

	sub vcl_recv {
		if (req.method == "PURGE") {
			return (purge);
		}
	}

	sub vcl_backend_response {
		set beresp.ttl = 0.01s;
		set beresp.grace = 0s;
		set beresp.keep = 10m;
		set beresp.http.was-304 = beresp.was_304;
	}

	sub vcl_backend_refresh {
		vtc.barrier_sync("${b1_sock}");
		vtc.barrier_sync("${b2_sock}");
		set beresp.http.valid = obj_stale.is_valid;
	}

}

# let the object die
delay 0.01

# Object gets purged while we are revalidating it
client c5 {
	txreq
	rxresp
	expect resp.status == 503
	expect resp.reason == "Invalid object for refresh"
} -start

barrier b1 sync

client c6 {
	txreq -method "PURGE"
	rxresp
	expect resp.status == 200
} -run

barrier b2 sync

server s1 -wait
client c5 -wait

###################################################################

server s1 {
	rxreq
	txresp
	rxreq
	txresp -status 304
} -start

vinyl v1 -vcl+backend {
	sub vcl_backend_response {
		set beresp.ttl = 0.01s;
		set beresp.grace = 0s;
		set beresp.keep = 10m;
		set beresp.http.was-304 = beresp.was_304;
	}

}

# Unprompted 304
client c7 {
	txreq -url /1
	rxresp
	expect resp.status == 200

	delay 0.01
	txreq -url /1
	rxresp
	expect resp.status == 503
	expect resp.reason == "Unexpected 304"
} -run

###################################################################

server s1 {
	rxreq
	txresp -status 404
	rxreq
	txresp -status 304
} -start

vinyl v1 -vcl+backend {

	sub vcl_backend_response {
		set beresp.ttl = 0.01s;
		set beresp.grace = 0s;
		set beresp.keep = 10m;
		set beresp.http.was-304 = beresp.was_304;
	}

	sub vcl_backend_fetch {
		set bereq.http.if-none-match = "abcd";
	}

}

# Receiving 304 for non-200 objects
client c8 {
	txreq -url /2
	rxresp
	expect resp.status == 404
	delay 0.01
	txreq -url /2
	rxresp
	expect resp.status == 503
	expect resp.reason == "Invalid object for refresh (status)"
} -run

###################################################################
# overriding the status check, allowing 304 on non-200

server s1 {
	rxreq
	txresp -status 404 -body "precious"
	rxreq
	txresp -status 304
} -start

vinyl v1 -vcl+backend {

	sub vcl_backend_response {
		set beresp.ttl = 0.01s;
		set beresp.grace = 0s;
		set beresp.keep = 10m;
		set beresp.http.was-304 = beresp.was_304;
	}

	sub vcl_backend_fetch {
		set bereq.http.if-none-match = "abcd";
	}

	sub vcl_refresh_status {
		return;
	}
}

# Receiving 304 for non-200 objects, but accepting it
# (violating http)
client c8 {
	txreq -url /3
	rxresp
	expect resp.status == 404
	expect resp.body == "precious"
	delay 0.01
	txreq -url /3
	rxresp
	expect resp.status == 404
	expect resp.http.was-304 == true
	expect resp.body == "precious"
} -run
