From 63342860938f85b4c8d085b4e1d0ac5ff032100d Mon Sep 17 00:00:00 2001 From: phk Date: Tue, 8 Jul 2008 09:15:32 +0000 Subject: [PATCH] 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: svn+ssh://projects.linpro.no/svn/varnish/trunk@2902 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- .../bin/varnishtest/tests/v00005.vtc | 51 ++++++++++ varnish-cache/include/vrt.h | 20 +++- varnish-cache/lib/libvcl/vcc_backend.c | 97 ++++++++++++++++++- varnish-cache/lib/libvcl/vcc_fixed_token.c | 20 +++- 4 files changed, 175 insertions(+), 13 deletions(-) create mode 100644 varnish-cache/bin/varnishtest/tests/v00005.vtc diff --git a/varnish-cache/bin/varnishtest/tests/v00005.vtc b/varnish-cache/bin/varnishtest/tests/v00005.vtc new file mode 100644 index 00000000..f582de9c --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/v00005.vtc @@ -0,0 +1,51 @@ +# $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 = "/"; + } + } +} diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index a8eb9b47..49cfeb14 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -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; }; /* diff --git a/varnish-cache/lib/libvcl/vcc_backend.c b/varnish-cache/lib/libvcl/vcc_backend.c index 1283f2fd..484d2d83 100644 --- a/varnish-cache/lib/libvcl/vcc_backend.c +++ b/varnish-cache/lib/libvcl/vcc_backend.c @@ -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); diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 85b715f1..da89ee4b 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -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"); -- 2.39.5