MEDIUM: da: HTX mode support.
The DeviceAtlas module now can support both the legacy
mode and the new HTX's with the known set of support headers
for the latter.
diff --git a/src/da.c b/src/da.c
index 50862a1..6c7ce81 100644
--- a/src/da.c
+++ b/src/da.c
@@ -7,6 +7,7 @@
#include <types/global.h>
#include <proto/arg.h>
#include <proto/http_fetch.h>
+#include <proto/http_htx.h>
#include <proto/log.h>
#include <proto/proto_http.h>
#include <proto/sample.h>
@@ -285,83 +286,164 @@
static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct hdr_idx *hidx;
- struct hdr_ctx hctx;
- const struct http_msg *hmsg;
da_evidence_t ev[DA_MAX_HEADERS];
da_deviceinfo_t devinfo;
da_status_t status;
+ struct channel *chn;
char vbuf[DA_MAX_HEADERS][1024] = {{ 0 }};
int i, nbh = 0;
if (global_deviceatlas.daset == 0) {
- return 1;
+ return 0;
}
- CHECK_HTTP_MESSAGE_FIRST((smp->strm ? &smp->strm->req : NULL));
- smp->data.type = SMP_T_STR;
+ chn = (smp->strm ? &smp->strm->req : NULL);
+ /* HTX Mode check */
+ if (smp->px->options2 & PR_O2_USE_HTX) {
+ struct htx_blk *blk;
+ struct htx *htx = smp_prefetch_htx(smp, chn, 1);
+ if (!htx) {
+ return 0;
+ }
- /**
- * Here we go through the whole list of headers from start
- * they will be filtered via the DeviceAtlas API itself
- */
- hctx.idx = 0;
- hidx = &smp->strm->txn->hdr_idx;
- hmsg = &smp->strm->txn->req;
+ i = 0;
+ for (blk = htx_get_head_blk(htx); nbh < DA_MAX_HEADERS && blk; blk = htx_get_next_blk(htx, blk)) {
+ size_t vlen;
+ char *pval;
+ da_evidence_id_t evid;
+ enum htx_blk_type type;
+ struct ist n, v;
+ char hbuf[24] = { 0 };
+ char tval[1024] = { 0 };
- while (http_find_next_header(ci_head(hmsg->chn), hidx, &hctx) == 1 &&
- nbh < DA_MAX_HEADERS) {
- char *pval;
- size_t vlen;
- da_evidence_id_t evid = -1;
- char hbuf[24] = { 0 };
+ type = htx_get_blk_type(blk);
- /* The HTTP headers used by the DeviceAtlas API are not longer */
- if (hctx.del >= sizeof(hbuf) || hctx.del <= 0 || hctx.vlen <= 0) {
- continue;
- }
+ if (type == HTX_BLK_HDR) {
+ n = htx_get_blk_name(htx, blk);
+ v = htx_get_blk_value(htx, blk);
+ } else if (type == HTX_BLK_EOH) {
+ break;
+ } else {
+ continue;
+ }
+
+ /* The HTTP headers used by the DeviceAtlas API are not longer */
+ if (n.len >= sizeof(hbuf)) {
+ continue;
+ }
+
+ memcpy(hbuf, n.ptr, n.len);
+ hbuf[n.len] = 0;
+ pval = v.ptr;
+ vlen = v.len;
+ evid = -1;
+ i = v.len > sizeof(tval) - 1 ? sizeof(tval) - 1 : v.len;
+ memcpy(tval, v.ptr, i);
+ tval[i] = 0;
+ pval = tval;
+
+ if (strcasecmp(hbuf, "Accept-Language") == 0) {
+ evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.atlas);
+ } else if (strcasecmp(hbuf, "Cookie") == 0) {
+ char *p, *eval;
+ size_t pl;
- vlen = hctx.vlen;
- memcpy(hbuf, hctx.line, hctx.del);
- hbuf[hctx.del] = 0;
- pval = (hctx.line + hctx.val);
+ eval = pval + vlen;
+ /**
+ * The cookie value, if it exists, is located between the current header's
+ * value position and the next one
+ */
+ if (http_extract_cookie_value(pval, eval, global_deviceatlas.cookiename,
+ global_deviceatlas.cookienamelen, 1, &p, &pl) == NULL) {
+ continue;
+ }
- if (strcmp(hbuf, "Accept-Language") == 0) {
- evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.
- atlas);
- } else if (strcmp(hbuf, "Cookie") == 0) {
- char *p, *eval;
- size_t pl;
+ vlen -= global_deviceatlas.cookienamelen - 1;
+ pval = p;
+ evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
+ } else {
+ evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas, hbuf);
+ }
- eval = pval + hctx.vlen;
- /**
- * The cookie value, if it exists, is located between the current header's
- * value position and the next one
- */
- if (http_extract_cookie_value(pval, eval, global_deviceatlas.cookiename,
- global_deviceatlas.cookienamelen, 1, &p, &pl) == NULL) {
+ if (evid == -1) {
continue;
}
- vlen = (size_t)pl;
- pval = p;
- evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
- } else {
- evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas,
- hbuf);
+ i = vlen > sizeof(vbuf[nbh]) - 1 ? sizeof(vbuf[nbh]) - 1 : vlen;
+ memcpy(vbuf[nbh], pval, i);
+ vbuf[nbh][i] = 0;
+ ev[nbh].key = evid;
+ ev[nbh].value = vbuf[nbh];
+ ++ nbh;
}
+ } else {
+ struct hdr_idx *hidx;
+ struct hdr_ctx hctx;
+ const struct http_msg *hmsg;
+ CHECK_HTTP_MESSAGE_FIRST(chn);
+ smp->data.type = SMP_T_STR;
- if (evid == -1) {
- continue;
- }
+ /**
+ * Here we go through the whole list of headers from start
+ * they will be filtered via the DeviceAtlas API itself
+ */
+ hctx.idx = 0;
+ hidx = &smp->strm->txn->hdr_idx;
+ hmsg = &smp->strm->txn->req;
+
+ while (http_find_next_header(ci_head(hmsg->chn), hidx, &hctx) == 1 &&
+ nbh < DA_MAX_HEADERS) {
+ char *pval;
+ size_t vlen;
+ da_evidence_id_t evid = -1;
+ char hbuf[24] = { 0 };
+
+ /* The HTTP headers used by the DeviceAtlas API are not longer */
+ if (hctx.del >= sizeof(hbuf) || hctx.del <= 0 || hctx.vlen <= 0) {
+ continue;
+ }
+
+ vlen = hctx.vlen;
+ memcpy(hbuf, hctx.line, hctx.del);
+ hbuf[hctx.del] = 0;
+ pval = (hctx.line + hctx.val);
- i = vlen > sizeof(vbuf[nbh]) ? sizeof(vbuf[nbh]) : vlen;
- memcpy(vbuf[nbh], pval, i - 1);
- vbuf[nbh][i - 1] = 0;
- ev[nbh].key = evid;
- ev[nbh].value = vbuf[nbh];
- ev[nbh].value[vlen] = 0;
- ++ nbh;
+ if (strcmp(hbuf, "Accept-Language") == 0) {
+ evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.
+ atlas);
+ } else if (strcmp(hbuf, "Cookie") == 0) {
+ char *p, *eval;
+ size_t pl;
+
+ eval = pval + hctx.vlen;
+ /**
+ * The cookie value, if it exists, is located between the current header's
+ * value position and the next one
+ */
+ if (http_extract_cookie_value(pval, eval, global_deviceatlas.cookiename,
+ global_deviceatlas.cookienamelen, 1, &p, &pl) == NULL) {
+ continue;
+ }
+
+ vlen = (size_t)pl;
+ pval = p;
+ evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
+ } else {
+ evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas,
+ hbuf);
+ }
+
+ if (evid == -1) {
+ continue;
+ }
+
+ i = vlen > sizeof(vbuf[nbh]) ? sizeof(vbuf[nbh]) : vlen;
+ memcpy(vbuf[nbh], pval, i - 1);
+ vbuf[nbh][i - 1] = 0;
+ ev[nbh].key = evid;
+ ev[nbh].value = vbuf[nbh];
+ ++ nbh;
+ }
}
status = da_searchv(&global_deviceatlas.atlas, &devinfo,
@@ -372,10 +454,10 @@
static struct cfg_kw_list dacfg_kws = {{ }, {
{ CFG_GLOBAL, "deviceatlas-json-file", da_json_file },
- { CFG_GLOBAL, "deviceatlas-log-level", da_log_level },
- { CFG_GLOBAL, "deviceatlas-property-separator", da_property_separator },
- { CFG_GLOBAL, "deviceatlas-properties-cookie", da_properties_cookie },
- { 0, NULL, NULL },
+ { CFG_GLOBAL, "deviceatlas-log-level", da_log_level },
+ { CFG_GLOBAL, "deviceatlas-property-separator", da_property_separator },
+ { CFG_GLOBAL, "deviceatlas-properties-cookie", da_properties_cookie },
+ { 0, NULL, NULL },
}};
INITCALL1(STG_REGISTER, cfg_register_keywords, &dacfg_kws);
@@ -383,7 +465,7 @@
/* Note: must not be declared <const> as its list will be overwritten */
static struct sample_fetch_kw_list fetch_kws = {ILH, {
{ "da-csv-fetch", da_haproxy_fetch, ARG12(1,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_USE_HRQHV },
- { NULL, NULL, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0 },
}};
INITCALL1(STG_REGISTER, sample_register_fetches, &fetch_kws);
@@ -391,7 +473,7 @@
/* Note: must not be declared <const> as its list will be overwritten */
static struct sample_conv_kw_list conv_kws = {ILH, {
{ "da-csv-conv", da_haproxy_conv, ARG12(1,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_T_STR },
- { NULL, NULL, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0 },
}};
static void da_haproxy_register_build_options()