Commit e1523131 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add VCC support for backend probe specifications.

It is possible to specify just the URL to be probed, or to specify the
entire HTTP request:

	backend b0 {
		.host = "127.0.0.1";
		.probe = {
			.url = "/test.jpg";
			.timeout = 224 ms;
		}
	}

	backend b1 {
		.host = "127.0.0.1";
		.probe = {
			# NB: \r\n automatically inserted after each string!
			.request =
			    "GET / HTTP/1.1"
			    "Host: www.foo.bar"
			    "Connection: close";
			.timeout = 0.3 s;
		}
	}

If the full request has not been completed within the timeout, the
backend will be set to down.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2902 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 8e6347d6
# $Id$
test "VCL: test backend probe syntax"
# Check url definition
varnish v1 -vcl {
backend b1 {
.host = "localhost";
.probe = {
.url = "/";
}
}
}
# Check request definition
varnish v1 -vcl {
backend b1 {
.host = "localhost";
.probe = {
.request =
"GET / HTTP/1.1"
"Host: foo.bar" ;
}
}
}
# Check redefinition
varnish v1 -badvcl {
backend b1 {
.host = "localhost";
.probe = {
.url = "/";
.request =
"GET / HTTP/1.1"
"Host: foo.bar" ;
}
}
}
# Check redefinition the other way
varnish v1 -badvcl {
backend b1 {
.host = "localhost";
.probe = {
.request =
"GET / HTTP/1.1"
"Host: foo.bar" ;
.url = "/";
}
}
}
......@@ -41,15 +41,25 @@ struct director;
struct VCL_conf;
struct sockaddr;
/*
* A backend probe specification
*/
struct vrt_backend_probe {
char *request;
double timeout;
};
/*
* A backend is a host+port somewhere on the network
*/
struct vrt_backend {
char *portname;
char *hostname;
char *vcl_name;
char *ident;
double connect_timeout;
char *portname;
char *hostname;
char *vcl_name;
char *ident;
double connect_timeout;
struct vrt_backend_probe probe;
};
/*
......
......@@ -216,6 +216,89 @@ vcc_FieldsOk(struct tokenlist *tl, const struct fld_spec *fs)
}
}
/*--------------------------------------------------------------------
* Parse a backend probe specification
*/
static void
vcc_ProbeRedef(struct tokenlist *tl, struct token **t_did, struct token *t_field)
{
if (*t_did != NULL) {
vsb_printf(tl->sb,
"Probe request redefinition at:\n");
vcc_ErrWhere(tl, t_field);
vsb_printf(tl->sb,
"Previous definition:\n");
vcc_ErrWhere(tl, *t_did);
return;
}
*t_did = t_field;
}
static void
vcc_ParseProbe(struct tokenlist *tl)
{
struct fld_spec *fs;
struct token *t_field;
struct token *t_did = NULL;
fs = vcc_FldSpec(tl, "?url", "?request", "?timeout", NULL);
ExpectErr(tl, '{');
vcc_NextToken(tl);
Fh(tl, 0, "\t.probe = {\n");
while (tl->t->tok != '}') {
vcc_IsField(tl, &t_field, fs);
ERRCHK(tl);
if (tl->err)
break;
if (vcc_IdIs(t_field, "url")) {
vcc_ProbeRedef(tl, &t_did, t_field);
ERRCHK(tl);
ExpectErr(tl, CSTR);
Fh(tl, 0, "\t\t.request =\n");
Fh(tl, 0, "\t\t\t\"GET \" ");
EncToken(tl->fh, tl->t);
Fh(tl, 0, " \" /HTTP/1.1\\r\\n\"\n");
Fh(tl, 0, "\t\t\t\"Connection: close\\r\\n\"\n");
Fh(tl, 0, "\t\t\t\"\\r\\n\",\n");
vcc_NextToken(tl);
} else if (vcc_IdIs(t_field, "request")) {
vcc_ProbeRedef(tl, &t_did, t_field);
ERRCHK(tl);
ExpectErr(tl, CSTR);
Fh(tl, 0, "\t\t.request =\n");
while (tl->t->tok == CSTR) {
Fh(tl, 0, "\t\t\t");
EncToken(tl->fh, tl->t);
Fh(tl, 0, " \"\\r\\n\"\n");
vcc_NextToken(tl);
}
Fh(tl, 0, "\t\t\t\"\\r\\n\",\n");
} else if (vcc_IdIs(t_field, "timeout")) {
Fh(tl, 0, "\t\t.timeout = ");
tl->fb = tl->fh;
vcc_TimeVal(tl);
tl->fb = NULL;
ERRCHK(tl);
Fh(tl, 0, ",\n");
} else {
vcc_ErrToken(tl, t_field);
vcc_ErrWhere(tl, t_field);
ErrInternal(tl);
return;
}
ExpectErr(tl, ';');
vcc_NextToken(tl);
}
Fh(tl, 0, "\t},\n");
ExpectErr(tl, '}');
vcc_NextToken(tl);
}
/*--------------------------------------------------------------------
* Parse and emit a backend host definition
*
......@@ -244,7 +327,8 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, const
const char *ep;
struct fld_spec *fs;
fs = vcc_FldSpec(tl, "!host", "?port", "?connect_timeout", NULL);
fs = vcc_FldSpec(tl,
"!host", "?port", "?connect_timeout", "?probe", NULL);
t_first = tl->t;
ExpectErr(tl, '{');
......@@ -276,11 +360,15 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, const
assert(tl->t->dec != NULL);
t_host = tl->t;
vcc_NextToken(tl);
ExpectErr(tl, ';');
vcc_NextToken(tl);
} else if (vcc_IdIs(t_field, "port")) {
ExpectErr(tl, CSTR);
assert(tl->t->dec != NULL);
t_port = tl->t;
vcc_NextToken(tl);
ExpectErr(tl, ';');
vcc_NextToken(tl);
} else if (vcc_IdIs(t_field, "connect_timeout")) {
Fh(tl, 0, "\t.connect_timeout = ");
tl->fb = tl->fh;
......@@ -288,13 +376,16 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, const
tl->fb = NULL;
ERRCHK(tl);
Fh(tl, 0, ",\n");
ExpectErr(tl, ';');
vcc_NextToken(tl);
} else if (vcc_IdIs(t_field, "probe")) {
vcc_ParseProbe(tl);
ERRCHK(tl);
} else {
ErrInternal(tl);
return;
}
ExpectErr(tl, ';');
vcc_NextToken(tl);
}
vcc_FieldsOk(tl, fs);
......
......@@ -380,14 +380,24 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, "struct sockaddr;\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "/*\n");
vsb_cat(sb, " * A backend probe specification\n");
vsb_cat(sb, " */\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "struct vrt_backend_probe {\n");
vsb_cat(sb, " char *request;\n");
vsb_cat(sb, " double timeout;\n");
vsb_cat(sb, "};\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "/*\n");
vsb_cat(sb, " * A backend is a host+port somewhere on the network\n");
vsb_cat(sb, " */\n");
vsb_cat(sb, "struct vrt_backend {\n");
vsb_cat(sb, " char *portname;\n");
vsb_cat(sb, " char *hostname;\n");
vsb_cat(sb, " char *vcl_name;\n");
vsb_cat(sb, " char *ident;\n");
vsb_cat(sb, " double connect_timeout;\n");
vsb_cat(sb, " char *portname;\n");
vsb_cat(sb, " char *hostname;\n");
vsb_cat(sb, " char *vcl_name;\n");
vsb_cat(sb, " char *ident;\n");
vsb_cat(sb, " double connect_timeout;\n");
vsb_cat(sb, " struct vrt_backend_probe probe;\n");
vsb_cat(sb, "};\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "/*\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment