[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