diff --git a/doc/configuration.txt b/doc/configuration.txt index c1f6f8219..dd8d5889a 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -15150,6 +15150,13 @@ http_date([]) microseconds since epoch. Offset is assumed to have the same unit as input timestamp. +iif(,) + Returns the string if the input value is true. Returns the + string otherwise. + + Example: + http-request set-header x-forwarded-proto %[ssl_fc,iff(https,http)] + in_table() Uses the string representation of the input sample to perform a look up in the specified table. If the key is not found in the table, a boolean false diff --git a/reg-tests/converter/iif.vtc b/reg-tests/converter/iif.vtc new file mode 100644 index 000000000..360b63f96 --- /dev/null +++ b/reg-tests/converter/iif.vtc @@ -0,0 +1,45 @@ +varnishtest "iif converter Test" + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp +} -repeat 3 -start + +haproxy h1 -conf { + defaults + mode http + timeout connect 1s + timeout client 1s + timeout server 1s + + frontend fe + bind "fd@${fe}" + + #### requests + http-request set-var(txn.iif) req.hdr_cnt(count),iif(ok,ko) + http-response set-header iif %[var(txn.iif)] + + default_backend be + + backend be + server s1 ${s1_addr}:${s1_port} +} -start + +client c1 -connect ${h1_fe_sock} { + txreq + rxresp + expect resp.status == 200 + expect resp.http.iif == "ko" + txreq \ + -hdr "count: 1" + rxresp + expect resp.status == 200 + expect resp.http.iif == "ok" + txreq \ + -hdr "count: 1,2" + rxresp + expect resp.status == 200 + expect resp.http.iif == "ok" +} -run diff --git a/src/sample.c b/src/sample.c index 3a1534865..a9c08ef54 100644 --- a/src/sample.c +++ b/src/sample.c @@ -3121,6 +3121,26 @@ static int sample_conv_secure_memcmp(const struct arg *arg_p, struct sample *smp } #endif +/* Takes a boolean as input. Returns the first argument if that boolean is true and + * the second argument otherwise. + */ +static int sample_conv_iif(const struct arg *arg_p, struct sample *smp, void *private) +{ + smp->data.type = SMP_T_STR; + smp->flags |= SMP_F_CONST; + + if (smp->data.u.sint) { + smp->data.u.str.data = arg_p[0].data.str.data; + smp->data.u.str.area = arg_p[0].data.str.area; + } + else { + smp->data.u.str.data = arg_p[1].data.str.data; + smp->data.u.str.area = arg_p[1].data.str.area; + } + + return 1; +} + #define GRPC_MSG_COMPRESS_FLAG_SZ 1 /* 1 byte */ #define GRPC_MSG_LENGTH_SZ 4 /* 4 bytes */ #define GRPC_MSG_HEADER_SZ (GRPC_MSG_COMPRESS_FLAG_SZ + GRPC_MSG_LENGTH_SZ) @@ -3782,6 +3802,8 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "ungrpc", sample_conv_ungrpc, ARG2(1,PBUF_FNUM,STR), sample_conv_protobuf_check, SMP_T_BIN, SMP_T_BIN }, { "protobuf", sample_conv_protobuf, ARG2(1,PBUF_FNUM,STR), sample_conv_protobuf_check, SMP_T_BIN, SMP_T_BIN }, + { "iif", sample_conv_iif, ARG2(2, STR, STR), NULL, SMP_T_BOOL, SMP_T_STR }, + { "and", sample_conv_binary_and, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT }, { "or", sample_conv_binary_or, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT }, { "xor", sample_conv_binary_xor, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT },