]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: WURFL: HTX awareness.
authormbellomi <massimiliano@scientiamobile.com>
Tue, 21 May 2019 15:15:07 +0000 (17:15 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 22 May 2019 10:06:38 +0000 (12:06 +0200)
Now wurfl fetch process is fully  HTX aware.

src/wurfl.c

index ae3d2fc00990920a345a7366d13264a153984a16..d1876014d557f1c82d3bf10d170e5dfd9258612f 100644 (file)
@@ -10,6 +10,8 @@
 #include <proto/arg.h>
 #include <proto/log.h>
 #include <proto/proto_http.h>
+#include <proto/http_fetch.h>
+#include <proto/http_htx.h>
 #include <proto/sample.h>
 #include <ebsttree.h>
 #include <ebmbtree.h>
@@ -428,9 +430,27 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
        struct buffer *temp;
        wurfl_information_t *wi;
        ha_wurfl_header_t wh;
+       struct channel *chn;
 
        ha_wurfl_log("WURFL: starting ha_wurfl_get_all\n");
+
+       chn = (smp->strm ? &smp->strm->req : NULL);
+
+       if (smp->px->options2 & PR_O2_USE_HTX) {
+               /* HTX version */
+               struct htx *htx = smp_prefetch_htx(smp, chn, 1);
+
+               if (!htx) {
+                       return 0;
+               }
+
+       } else {
+               /* Legacy version */
+               CHECK_HTTP_MESSAGE_FIRST(chn);
+       }
+
        wh.wsmp = smp;
+
        dHandle = wurfl_lookup(global_wurfl.handle, &ha_wurfl_retrieve_header, &wh);
 
        temp = get_trash_chunk();
@@ -493,6 +513,7 @@ wurfl_get_all_completed:
                --smp->data.u.str.data;
        }
 
+       smp->data.type = SMP_T_STR;
        return 1;
 }
 
@@ -504,9 +525,27 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
        struct ebmb_node *node;
        ha_wurfl_header_t wh;
        int i = 0;
+       struct channel *chn;
 
        ha_wurfl_log("WURFL: starting ha_wurfl_get\n");
+
+       chn = (smp->strm ? &smp->strm->req : NULL);
+
+       if (smp->px->options2 & PR_O2_USE_HTX) {
+               /* HTX version */
+               struct htx *htx = smp_prefetch_htx(smp, chn, 1);
+
+               if (!htx) {
+                       return 0;
+               }
+
+       } else {
+               /* Legacy version */
+               CHECK_HTTP_MESSAGE_FIRST(chn);
+       }
+
        wh.wsmp = smp;
+
        dHandle = wurfl_lookup(global_wurfl.handle, &ha_wurfl_retrieve_header, &wh);
 
        temp = get_trash_chunk();
@@ -581,6 +620,7 @@ wurfl_get_completed:
                --smp->data.u.str.data;
        }
 
+       smp->data.type = SMP_T_STR;
        return 1;
 }
 
@@ -700,25 +740,80 @@ static const char *(*ha_wurfl_get_property_callback(char *name)) (wurfl_handle w
 static const char *ha_wurfl_retrieve_header(const char *header_name, const void *wh)
 {
        struct sample *smp;
-       struct hdr_idx *idx;
-       struct hdr_ctx ctx;
-       const struct http_msg *msg;
+       struct channel *chn;
        int header_len = HA_WURFL_MAX_HEADER_LENGTH;
 
-       ha_wurfl_log("WURFL: retrieve header request [%s]\n", header_name);
        smp =  ((ha_wurfl_header_t *)wh)->wsmp;
-       idx = &smp->strm->txn->hdr_idx;
-       msg = &smp->strm->txn->req;
-       ctx.idx = 0;
+       chn = (smp->strm ? &smp->strm->req : NULL);
+
+       if (smp->px->options2 & PR_O2_USE_HTX) {
+               /* HTX version */
+               struct htx *htx;
+               struct http_hdr_ctx ctx;
+               struct ist name;
 
-       if (http_find_full_header2(header_name, strlen(header_name), ci_head(msg->chn), idx, &ctx) == 0)
-               return 0;
+               ha_wurfl_log("WURFL: retrieve header (HTX) request [%s]\n", header_name);
 
-       if (header_len > ctx.vlen)
-               header_len = ctx.vlen;
+               //the header is searched from the beginning
+               ctx.blk = NULL;
+
+               // We could skip this chek since ha_wurfl_retrieve_header is called from inside
+               // ha_wurfl_get()/ha_wurfl_get_all() that already perform the same check
+               // We choose to keep it in case ha_wurfl_retrieve_header will be called directly
+               htx = smp_prefetch_htx(smp, chn, 1);
+               if (!htx) {
+                       return NULL;
+               }
+
+               name.ptr = (char *)header_name;
+               name.len = strlen(header_name);
+
+               // If 4th param is set, it works on full-line headers in whose comma is not a delimiter but is
+               // part of the syntax
+               if (!http_find_header(htx, name, &ctx, 1)) {
+                       return NULL;
+               }
+
+               if (header_len > ctx.value.len)
+                       header_len = ctx.value.len;
+
+               strncpy(((ha_wurfl_header_t *)wh)->header_value, ctx.value.ptr, header_len);
+
+       } else {
+               /* Legacy version */
+               struct http_txn *txn;
+               struct hdr_idx *idx;
+               struct hdr_ctx ctx;
+               int res;
+
+               ha_wurfl_log("WURFL: retrieve header (legacy) request [%s]\n", header_name);
+
+               // We could skip this chek since ha_wurfl_retrieve_header is called from inside
+               // ha_wurfl_get()/ha_wurfl_get_all() that already perform the same check
+               // We choose to keep it in case ha_wurfl_retrieve_header will be called directly
+               // This is a version of CHECK_HTTP_MESSAGE_FIRST(chn) which returns NULL in case of error
+               res = smp_prefetch_http(smp->px, smp->strm, smp->opt, (chn), smp, 1);
+               if (res <= 0) {
+                       return NULL;
+               }
+
+               txn = smp->strm->txn;
+               idx = &txn->hdr_idx;
+
+               ctx.idx = 0;
+
+               if (http_find_full_header2(header_name, strlen(header_name), ci_head(chn), idx, &ctx) == 0)
+                       return NULL;
+
+               if (header_len > ctx.vlen)
+                       header_len = ctx.vlen;
+
+               strncpy(((ha_wurfl_header_t *)wh)->header_value, ctx.line + ctx.val, header_len);
+
+       }
 
-       strncpy(((ha_wurfl_header_t *)wh)->header_value, ctx.line + ctx.val, header_len);
        ((ha_wurfl_header_t *)wh)->header_value[header_len] = '\0';
+
        ha_wurfl_log("WURFL: retrieve header request returns [%s]\n", ((ha_wurfl_header_t *)wh)->header_value);
        return ((ha_wurfl_header_t *)wh)->header_value;
 }