diff --git a/src/wurfl.c b/src/wurfl.c index ae3d2fc00..d1876014d 100644 --- a/src/wurfl.c +++ b/src/wurfl.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 (http_find_full_header2(header_name, strlen(header_name), ci_head(msg->chn), idx, &ctx) == 0) - return 0; + if (smp->px->options2 & PR_O2_USE_HTX) { + /* HTX version */ + struct htx *htx; + struct http_hdr_ctx ctx; + struct ist name; - if (header_len > ctx.vlen) - header_len = ctx.vlen; + ha_wurfl_log("WURFL: retrieve header (HTX) request [%s]\n", header_name); + + //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; }