]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: merge acl and pattern header fetch functions
authorWilly Tarreau <w@1wt.eu>
Thu, 26 Apr 2012 13:11:51 +0000 (15:11 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:19 +0000 (20:57 +0200)
HTTP header fetch is now done using smp_fetch_hdr() for both ACLs and
patterns. This one also supports an occurrence number, making it possible
to specify explicit occurrences for ACLs and patterns.

doc/configuration.txt
include/proto/proto_http.h
src/proto_http.c

index 20bb05055c857a722755361c2ad9ea19ed24f12f..979af6336b454b380df4a98b0fbe7b78c7ecfbdf 100644 (file)
@@ -7927,12 +7927,16 @@ cook_sub(<name>) <string>
   scook_sub() variant for response cookies sent by the server.
 
 hdr <string>
-hdr(<header>) <string>
+hdr(<header>[,<occ>]) <string>
   Note: all the "hdr*" matching criteria either apply to all headers, or to a
   particular header whose name is passed between parenthesis and without any
   space. The header name is not case-sensitive. The header matching complies
   with RFC2616, and treats as separate headers all values delimited by commas.
-  Use the shdr() variant for response headers sent by the server.
+  If an occurrence number is specified as the optional second argument, only
+  this occurrence will be considered. Positive values indicate a position from
+  the first occurrence, 1 being the first one. Negative values indicate
+  positions relative to the last one, -1 being the last one. Use the shdr()
+  variant for response headers sent by the server.
 
   The "hdr" criteria returns true if any of the headers matching the criteria
   match any of the strings. This can be used to check for exact values. For
@@ -7941,7 +7945,7 @@ hdr(<header>) <string>
      hdr(Connection) -i close
 
 hdr_beg <string>
-hdr_beg(<header>) <string>
+hdr_beg(<header>[,<occ>]) <string>
   Returns true when one of the headers begins with one of the strings. See
   "hdr" for more information on header matching. Use the shdr_beg() variant for
   response headers sent by the server.
@@ -7957,7 +7961,7 @@ hdr_cnt(<header>) <integer>
   the shdr_cnt() variant for response headers sent by the server.
 
 hdr_dir <string>
-hdr_dir(<header>) <string>
+hdr_dir(<header>[,<occ>]) <string>
   Returns true when one of the headers contains one of the strings either
   isolated or delimited by slashes. This is used to perform filename or
   directory name matching, and may be used with Referer. See "hdr" for more
@@ -7965,7 +7969,7 @@ hdr_dir(<header>) <string>
   headers sent by the server.
 
 hdr_dom <string>
-hdr_dom(<header>) <string>
+hdr_dom(<header>[,<occ>]) <string>
   Returns true when one of the headers contains one of the strings either
   isolated or delimited by dots. This is used to perform domain name matching,
   and may be used with the Host header. See "hdr" for more information on
@@ -7973,27 +7977,27 @@ hdr_dom(<header>) <string>
   server.
 
 hdr_end <string>
-hdr_end(<header>) <string>
+hdr_end(<header>[,<occ>]) <string>
   Returns true when one of the headers ends with one of the strings. See "hdr"
   for more information on header matching. Use the shdr_end() variant for
   response headers sent by the server.
 
 hdr_ip <ip_address>
-hdr_ip(<header>) <ip_address>
+hdr_ip(<header>[,<occ>]) <ip_address>
   Returns true when one of the headers' values contains an IP address matching
   <ip_address>. This is mainly used with headers such as X-Forwarded-For or
   X-Client-IP. See "hdr" for more information on header matching. Use the
   shdr_ip() variant for response headers sent by the server.
 
 hdr_len <integer>
-hdr_len(<header>) <integer>
+hdr_len(<header>[,<occ>]) <integer>
   Returns true when at least one of the headers has a length which matches the
   values or ranges specified. This may be used to detect empty or too large
   headers. See "hdr" for more information on header matching. Use the
   shdr_len() variant for response headers sent by the server.
 
 hdr_reg <regex>
-hdr_reg(<header>) <regex>
+hdr_reg(<header>[,<occ>]) <regex>
   Returns true it one of the headers matches one of the regular expressions. It
   can be used at any time, but it is important to remember that regex matching
   is slower than other methods. See also other "hdr_" criteria, as well as
@@ -8001,13 +8005,13 @@ hdr_reg(<header>) <regex>
   response headers sent by the server.
 
 hdr_sub <string>
-hdr_sub(<header>) <string>
+hdr_sub(<header>[,<occ>]) <string>
   Returns true when one of the headers contains one of the strings. See "hdr"
   for more information on header matching. Use the shdr_sub() variant for
   response headers sent by the server.
 
 hdr_val <integer>
-hdr_val(<header>) <integer>
+hdr_val(<header>[,<occ>]) <integer>
   Returns true when one of the headers starts with a number which matches the
   values or ranges specified. This may be used to limit content-length to
   acceptable values for example. See "hdr" for more information on header
@@ -8331,8 +8335,13 @@ The list of currently supported pattern fetch functions is the following :
                ports to some clients for a whole application session. It is of
                type integer and only works with such tables.
 
-  hdr(<name>)  This extracts the last occurrence of header <name> in an HTTP
-               request. A typical use is with the X-Forwarded-For header once
+  hdr(<name>[,<occ>])
+               This extracts the last occurrence of header <name> in an HTTP
+               request. Optionally, a specific occurrence might be specified as
+               a position number. Positive values indicate a position from the
+               first occurrence, with 1 being the first one. Negative values
+               indicate positions relative to the last one, with -1 being the
+               last one. A typical use is with the X-Forwarded-For header once
                converted to IP, associated with an IP stick-table.
 
   payload(<offset>,<length>)
index 16f03c2eb34b02fd26f3f38a2f43ce5e1f7fc9b1..06fe292574583f8bc7b2ac742d5e313b2652d946 100644 (file)
@@ -98,7 +98,7 @@ void http_return_srv_error(struct session *s, struct stream_interface *si);
 void http_capture_bad_message(struct error_snapshot *es, struct session *s,
                               struct http_msg *msg,
                              int state, struct proxy *other_end);
-unsigned int http_get_hdr(struct http_msg *msg, const char *hname, int hlen,
+unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hlen,
                          struct hdr_idx *idx, int occ,
                          struct hdr_ctx *ctx, char **vptr, int *vlen);
 
index 08750d7f75d84c1d2fd3f22dfe1a2b26eef77ed2..a1b7e136af8e0da6c59a4f265ed53a927458de40 100644 (file)
@@ -7261,7 +7261,7 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s,
  * -1.
  * The return value is 0 if nothing was found, or non-zero otherwise.
  */
-unsigned int http_get_hdr(struct http_msg *msg, const char *hname, int hlen,
+unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hlen,
                          struct hdr_idx *idx, int occ,
                          struct hdr_ctx *ctx, char **vptr, int *vlen)
 {
@@ -7843,39 +7843,54 @@ acl_fetch_url_port(struct proxy *px, struct session *l4, void *l7, unsigned int
        return 1;
 }
 
-/* 5. Check on HTTP header. A pointer to the beginning of the value is returned.
- * Accepts exactly 1 argument of type string.
+/* Fetch an HTTP header. A pointer to the beginning of the value is returned.
+ * Accepts an optional argument of type string containing the header field name,
+ * and an optional argument of type signed or unsigned integer to request an
+ * explicit occurrence of the header. Note that in the event of a missing name,
+ * headers are considered from the first one.
  */
 static int
-acl_fetch_hdr(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_hdr(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
               const struct arg *args, struct sample *smp)
 {
        struct http_txn *txn = l7;
        struct hdr_idx *idx = &txn->hdr_idx;
        struct hdr_ctx *ctx = (struct hdr_ctx *)smp->ctx.a;
        const struct http_msg *msg = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ) ? &txn->req : &txn->rsp;
+       int occ = 0;
+       const char *name_str = NULL;
+       int name_len = 0;
 
-       if (!args || args->type != ARGT_STR)
-               return 0;
+       if (args) {
+               if (args[0].type != ARGT_STR)
+                       return 0;
+               name_str = args[0].data.str.str;
+               name_len = args[0].data.str.len;
+
+               if (args[1].type == ARGT_UINT || args[1].type == ARGT_SINT)
+                       occ = args[1].data.uint;
+       }
 
        CHECK_HTTP_MESSAGE_FIRST();
 
-       if (!(smp->flags & SMP_F_NOT_LAST))
+       if (ctx && !(smp->flags & SMP_F_NOT_LAST))
                /* search for header from the beginning */
                ctx->idx = 0;
 
-       if (http_find_header2(args->data.str.str, args->data.str.len, msg->buf->p + msg->sol, idx, ctx)) {
+       if (!occ && !(opt & SMP_OPT_ITERATE))
+               /* no explicit occurrence and single fetch => last header by default */
+               occ = -1;
+
+       if (!occ)
+               /* prepare to report multiple occurrences for ACL fetches */
                smp->flags |= SMP_F_NOT_LAST;
-               smp->flags |= SMP_F_VOL_HDR;
-               smp->type = SMP_T_CSTR;
-               smp->data.str.str = (char *)ctx->line + ctx->val;
-               smp->data.str.len = ctx->vlen;
 
+       smp->type = SMP_T_CSTR;
+       smp->flags |= SMP_F_VOL_HDR;
+       if (http_get_hdr(msg, name_str, name_len, idx, occ, ctx, &smp->data.str.str, &smp->data.str.len))
                return 1;
-       }
 
        smp->flags &= ~SMP_F_NOT_LAST;
-       smp->flags |= SMP_F_VOL_HDR;
        return 0;
 }
 
@@ -7883,7 +7898,7 @@ acl_fetch_hdr(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
  * Accepts exactly 1 argument of type string.
  */
 static int
-acl_fetch_hdr_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_hdr_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                   const struct arg *args, struct sample *smp)
 {
        struct http_txn *txn = l7;
@@ -7908,14 +7923,16 @@ acl_fetch_hdr_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int o
        return 1;
 }
 
-/* 7. Check on HTTP header's integer value. The integer value is returned.
- * FIXME: the type is 'int', it may not be appropriate for everything.
+/* Fetch an HTTP header's integer value. The integer value is returned. It
+ * takes a mandatory argument of type string and an optional one of type int
+ * to designate a specific occurrence. It returns an unsigned integer, which
+ * may or may not be appropriate for everything.
  */
 static int
-acl_fetch_hdr_val(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_hdr_val(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                   const struct arg *args, struct sample *smp)
 {
-       int ret = acl_fetch_hdr(px, l4, l7, opt, args, smp);
+       int ret = smp_fetch_hdr(px, l4, l7, opt, args, smp);
 
        if (ret > 0) {
                smp->type = SMP_T_UINT;
@@ -7925,19 +7942,23 @@ acl_fetch_hdr_val(struct proxy *px, struct session *l4, void *l7, unsigned int o
        return ret;
 }
 
-/* 7. Check on HTTP header's IPv4 address value. The IPv4 address is returned.
+/* Fetch an HTTP header's integer value. The integer value is returned. It
+ * takes a mandatory argument of type string and an optional one of type int
+ * to designate a specific occurrence. It returns an IPv4 address.
  */
 static int
-acl_fetch_hdr_ip(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_hdr_ip(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                  const struct arg *args, struct sample *smp)
 {
        int ret;
 
-       while ((ret = acl_fetch_hdr(px, l4, l7, opt, args, smp)) > 0) {
+       while ((ret = smp_fetch_hdr(px, l4, l7, opt, args, smp)) > 0) {
                smp->type = SMP_T_IPV4;
                if (url2ipv4((char *)smp->data.str.str, &smp->data.ipv4))
                        break;
                /* if the header doesn't match an IP address, fetch next one */
+               if (!(smp->flags & SMP_F_NOT_LAST))
+                       return 0;
        }
        return ret;
 }
@@ -8260,18 +8281,6 @@ acl_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, unsigned in
 /*     The code below is dedicated to pattern fetching and matching     */
 /************************************************************************/
 
-/* Returns the last occurrence of specified header. */
-static int
-pattern_fetch_hdr(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
-                 const struct arg *arg_p, struct sample *smp)
-{
-       struct http_txn *txn = l7;
-
-       smp->type = SMP_T_CSTR;
-       return http_get_hdr(&txn->req, arg_p->data.str.str, arg_p->data.str.len, &txn->hdr_idx,
-                           -1, NULL, &smp->data.str.str, &smp->data.str.len);
-}
-
 /*
  * Given a path string and its length, find the position of beginning of the
  * query string. Returns NULL if no query string is found in the path.
@@ -8458,6 +8467,24 @@ pattern_fetch_set_cookie(struct proxy *px, struct session *l4, void *l7, unsigne
        return found;
 }
 
+/* This function is used to validate the arguments passed to any "hdr" fetch
+ * keyword. These keywords support an optional positive or negative occurrence
+ * number. We must ensure that the number is greater than -MAX_HDR_HISTORY. It
+ * is assumed that the types are already the correct ones. Returns 0 on error,
+ * non-zero if OK. If <err> is not NULL, it will be filled with a pointer to an
+ * error message in case of error, that the caller is responsible for freeing.
+ * The initial location must either be freeable or NULL.
+ */
+static int val_hdr(struct arg *arg, char **err_msg)
+{
+       if (arg && arg[1].type == ARGT_SINT && arg[1].data.sint < -MAX_HDR_HISTORY) {
+               if (err_msg)
+                       memprintf(err_msg, "header occurrence must be >= %d", -MAX_HDR_HISTORY);
+               return 0;
+       }
+       return 1;
+}
+
 /************************************************************************/
 /*          All supported ACL keywords must be declared here.           */
 /************************************************************************/
@@ -8476,17 +8503,17 @@ static struct acl_kw_list acl_kws = {{ },{
        { "cook_reg",        acl_parse_reg,     acl_fetch_cookie_value,   acl_match_reg,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
        { "cook_sub",        acl_parse_str,     acl_fetch_cookie_value,   acl_match_sub,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
 
-       { "hdr",             acl_parse_str,     acl_fetch_hdr,            acl_match_str,     ACL_USE_L7REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
-       { "hdr_beg",         acl_parse_str,     acl_fetch_hdr,            acl_match_beg,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_cnt",         acl_parse_int,     acl_fetch_hdr_cnt,        acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_dir",         acl_parse_str,     acl_fetch_hdr,            acl_match_dir,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_dom",         acl_parse_str,     acl_fetch_hdr,            acl_match_dom,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_end",         acl_parse_str,     acl_fetch_hdr,            acl_match_end,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_ip",          acl_parse_ip,      acl_fetch_hdr_ip,         acl_match_ip,      ACL_USE_L7REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
-       { "hdr_len",         acl_parse_int,     acl_fetch_hdr,            acl_match_len,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_reg",         acl_parse_reg,     acl_fetch_hdr,            acl_match_reg,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_sub",         acl_parse_str,     acl_fetch_hdr,            acl_match_sub,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-       { "hdr_val",         acl_parse_int,     acl_fetch_hdr_val,        acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
+       { "hdr",             acl_parse_str,     smp_fetch_hdr,            acl_match_str,     ACL_USE_L7REQ_VOLATILE|ACL_MAY_LOOKUP, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_beg",         acl_parse_str,     smp_fetch_hdr,            acl_match_beg,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_cnt",         acl_parse_int,     smp_fetch_hdr_cnt,        acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
+       { "hdr_dir",         acl_parse_str,     smp_fetch_hdr,            acl_match_dir,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_dom",         acl_parse_str,     smp_fetch_hdr,            acl_match_dom,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_end",         acl_parse_str,     smp_fetch_hdr,            acl_match_end,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_ip",          acl_parse_ip,      smp_fetch_hdr_ip,         acl_match_ip,      ACL_USE_L7REQ_VOLATILE|ACL_MAY_LOOKUP, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_len",         acl_parse_int,     smp_fetch_hdr,            acl_match_len,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_reg",         acl_parse_reg,     smp_fetch_hdr,            acl_match_reg,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_sub",         acl_parse_str,     smp_fetch_hdr,            acl_match_sub,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "hdr_val",         acl_parse_int,     smp_fetch_hdr_val,        acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
 
        { "http_auth",       acl_parse_nothing, acl_fetch_http_auth,      acl_match_nothing, ACL_USE_L7REQ_VOLATILE, ARG1(0,USR) },
        { "http_auth_group", acl_parse_strcat,  acl_fetch_http_auth,      acl_match_auth,    ACL_USE_L7REQ_VOLATILE, ARG1(0,USR) },
@@ -8517,17 +8544,17 @@ static struct acl_kw_list acl_kws = {{ },{
        { "scook_reg",       acl_parse_reg,     acl_fetch_cookie_value,   acl_match_reg,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
        { "scook_sub",       acl_parse_str,     acl_fetch_cookie_value,   acl_match_sub,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
 
-       { "shdr",            acl_parse_str,     acl_fetch_hdr,            acl_match_str,     ACL_USE_L7RTR_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
-       { "shdr_beg",        acl_parse_str,     acl_fetch_hdr,            acl_match_beg,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_cnt",        acl_parse_int,     acl_fetch_hdr_cnt,        acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_dir",        acl_parse_str,     acl_fetch_hdr,            acl_match_dir,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_dom",        acl_parse_str,     acl_fetch_hdr,            acl_match_dom,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_end",        acl_parse_str,     acl_fetch_hdr,            acl_match_end,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_ip",         acl_parse_ip,      acl_fetch_hdr_ip,         acl_match_ip,      ACL_USE_L7RTR_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
-       { "shdr_len",        acl_parse_int,     acl_fetch_hdr,            acl_match_len,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_reg",        acl_parse_reg,     acl_fetch_hdr,            acl_match_reg,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_sub",        acl_parse_str,     acl_fetch_hdr,            acl_match_sub,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-       { "shdr_val",        acl_parse_int,     acl_fetch_hdr_val,        acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
+       { "shdr",            acl_parse_str,     smp_fetch_hdr,            acl_match_str,     ACL_USE_L7RTR_VOLATILE|ACL_MAY_LOOKUP, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_beg",        acl_parse_str,     smp_fetch_hdr,            acl_match_beg,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_cnt",        acl_parse_int,     smp_fetch_hdr_cnt,        acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
+       { "shdr_dir",        acl_parse_str,     smp_fetch_hdr,            acl_match_dir,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_dom",        acl_parse_str,     smp_fetch_hdr,            acl_match_dom,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_end",        acl_parse_str,     smp_fetch_hdr,            acl_match_end,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_ip",         acl_parse_ip,      smp_fetch_hdr_ip,         acl_match_ip,      ACL_USE_L7RTR_VOLATILE|ACL_MAY_LOOKUP, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_len",        acl_parse_int,     smp_fetch_hdr,            acl_match_len,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_reg",        acl_parse_reg,     smp_fetch_hdr,            acl_match_reg,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_sub",        acl_parse_str,     smp_fetch_hdr,            acl_match_sub,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
+       { "shdr_val",        acl_parse_int,     smp_fetch_hdr_val,        acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
 
        { "status",          acl_parse_int,     acl_fetch_stcode,         acl_match_int,     ACL_USE_L7RTR_PERMANENT, 0 },
 
@@ -8560,7 +8587,7 @@ static struct acl_kw_list acl_kws = {{ },{
 /************************************************************************/
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
-       { "hdr",        pattern_fetch_hdr,        ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_REQ },
+       { "hdr",        smp_fetch_hdr,            ARG2(1,STR,SINT), val_hdr, SMP_T_CSTR, SMP_CAP_REQ },
        { "url_param",  smp_fetch_url_param,      ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_REQ },
        { "cookie",     pattern_fetch_cookie,     ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_REQ },
        { "set-cookie", pattern_fetch_set_cookie, ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_RES },