[master] 78c82e5 Add field operator
Martin Blix Grydeland
martin at varnish-cache.org
Tue Oct 1 14:48:18 CEST 2013
commit 78c82e5efe0db40614f749932591fa45bb4ea679
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Fri Sep 20 18:53:39 2013 +0200
Add field operator
diff --git a/bin/varnishtest/tests/l00001.vtc b/bin/varnishtest/tests/l00001.vtc
index 4d8c12d..3030d3e 100644
--- a/bin/varnishtest/tests/l00001.vtc
+++ b/bin/varnishtest/tests/l00001.vtc
@@ -6,6 +6,9 @@ server s1 {
} -start
varnish v1 -vcl+backend {
+ sub vcl_deliver {
+ set resp.http.x-test = "123 321";
+ }
} -start
logexpect l1 -v v1
@@ -162,3 +165,10 @@ logexpect l1 -d 1 -g vxid -q "RespStatus == 200 or RespStatus == 503 and RespSta
expect * = ReqEnd
expect * = End
} -run
+
+# Test field
+logexpect l1 -d 1 -g vxid -q "RespHeader[2] == 123" {
+ expect 0 * Begin req
+ expect * = ReqEnd
+ expect * = End
+} -run
diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c
index ba3d23b..e42705a 100644
--- a/lib/libvarnishapi/vsl_query.c
+++ b/lib/libvarnishapi/vsl_query.c
@@ -73,8 +73,7 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
const struct vex_rhs *rhs;
long long lhs_int;
double lhs_float;
- const char *lhs_string;
- size_t lhs_stringlen;
+ const char *b, *e;
char *p;
int i;
@@ -83,8 +82,26 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
rhs = vex->rhs;
AN(rhs);
- lhs_string = VSL_CDATA(rec->ptr);
- lhs_stringlen = VSL_LEN(rec->ptr) - 1;
+ b = VSL_CDATA(rec->ptr);
+ e = b + VSL_LEN(rec->ptr) - 1;
+
+ /* Field */
+ if (vex->lhs->field > 0) {
+ for (e = b, i = 0; *e && i < vex->lhs->field; i++) {
+ b = e;
+ /* Skip ws */
+ while (*b && isspace(*b))
+ b++;
+ e = b;
+ /* Skip non-ws */
+ while (*e && !isspace(*e))
+ e++;
+ }
+ assert(b <= e);
+ if (*b == '\0' || i < vex->lhs->field)
+ /* Missing field - no match */
+ return (0);
+ }
/* Prepare */
switch (vex->tok) {
@@ -95,15 +112,18 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
case T_LEQ: /* <= */
case T_GEQ: /* >= */
/* Numerical comparison */
+ if (*b == '\0')
+ /* Empty string doesn't match */
+ return (0);
switch (rhs->type) {
case VEX_INT:
- lhs_int = strtoll(lhs_string, &p, 0);
+ lhs_int = strtoll(b, &p, 0);
if (*p == '\0' || isspace(*p))
break;
/* Can't parse - no match */
return (0);
case VEX_FLOAT:
- lhs_float = strtod(lhs_string, &p);
+ lhs_float = strtod(b, &p);
if (*p == '\0' || isspace(*p))
break;
/* Can't parse - no match */
@@ -130,27 +150,25 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
case T_SEQ: /* eq */
assert(rhs->type == VEX_STRING);
- if (lhs_stringlen == rhs->val_stringlen &&
- !strncmp(lhs_string, rhs->val_string, lhs_stringlen))
+ if (e - b == rhs->val_stringlen &&
+ !strncmp(b, rhs->val_string, e - b))
return (1);
return (0);
case T_SNEQ: /* ne */
assert(rhs->type == VEX_STRING);
- if (lhs_stringlen != rhs->val_stringlen ||
- strncmp(lhs_string, rhs->val_string, lhs_stringlen))
+ if (e - b != rhs->val_stringlen ||
+ strncmp(b, rhs->val_string, e - b))
return (1);
return (0);
case '~': /* ~ */
assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
- i = VRE_exec(rhs->val_regex, lhs_string, lhs_stringlen, 0, 0,
- NULL, 0, NULL);
+ i = VRE_exec(rhs->val_regex, b, e - b, 0, 0, NULL, 0, NULL);
if (i != VRE_ERROR_NOMATCH)
return (1);
return (0);
case T_NOMATCH: /* !~ */
assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
- i = VRE_exec(rhs->val_regex, lhs_string, lhs_stringlen, 0, 0,
- NULL, 0, NULL);
+ i = VRE_exec(rhs->val_regex, b, e - b, 0, 0, NULL, 0, NULL);
if (i == VRE_ERROR_NOMATCH)
return (1);
return (0);
diff --git a/lib/libvarnishapi/vxp_parse.c b/lib/libvarnishapi/vxp_parse.c
index 2cc1288..aad8bde 100644
--- a/lib/libvarnishapi/vxp_parse.c
+++ b/lib/libvarnishapi/vxp_parse.c
@@ -50,6 +50,7 @@ static void vxp_expr_or(struct vxp *vxp, struct vex **pvex);
static void
vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
{
+ char *p;
/* XXX: Tag wildcards */
AN(plhs);
@@ -75,7 +76,27 @@ vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
}
vxp_NextToken(vxp);
- /* XXX: Lhs limiting operators ([], {}) */
+ if (vxp->t->tok == '[') {
+ /* LHS field [] */
+ vxp_NextToken(vxp);
+ if (vxp->t->tok != VAL) {
+ VSB_printf(vxp->sb, "Expected integer got '%.*s' ",
+ PF(vxp->t));
+ vxp_ErrWhere(vxp, vxp->t, -1);
+ return;
+ }
+ (*plhs)->field = (int)strtol(vxp->t->dec, &p, 0);
+ if (*p || (*plhs)->field <= 0) {
+ VSB_printf(vxp->sb, "Expected positive integer");
+ vxp_ErrWhere(vxp, vxp->t, -1);
+ return;
+ }
+ vxp_NextToken(vxp);
+ ExpectErr(vxp, ']');
+ vxp_NextToken(vxp);
+ }
+
+ /* XXX: LHS Level {} */
}
static void
@@ -460,6 +481,8 @@ vex_print(const struct vex *vex, int indent)
if (vex->lhs != NULL) {
CHECK_OBJ_NOTNULL(vex->lhs, VEX_LHS_MAGIC);
fprintf(stderr, " tag=%s", VSL_tags[vex->lhs->tag]);
+ if (vex->lhs->field >= 0)
+ fprintf(stderr, "[%d]", vex->lhs->field);
}
if (vex->rhs != NULL) {
fprintf(stderr, " ");
More information about the varnish-commit
mailing list