MEDIUM: http_fetch: Remove code relying on HTTP legacy mode

Since the legacy HTTP mode is disbabled, all HTTP sample fetches work on HTX
streams. So it is safe to remove all code relying on HTTP legacy mode. Among
other things, the function smp_prefetch_http() was removed with the associated
macros CHECK_HTTP_MESSAGE_FIRST() and CHECK_HTTP_MESSAGE_FIRST_PERM().
This commit is contained in:
Christopher Faulet 2019-07-15 14:36:03 +02:00
parent 9a7e8ce4eb
commit 6d1dd46917
5 changed files with 662 additions and 1854 deletions

View File

@ -23,25 +23,12 @@
#define _PROTO_HTTP_FETCH_H #define _PROTO_HTTP_FETCH_H
#include <common/config.h> #include <common/config.h>
#include <common/mini-clist.h> #include <common/htx.h>
#include <types/action.h> #include <types/arg.h>
#include <types/proxy.h> #include <types/channel.h>
#include <types/sample.h>
/* Note: these functions *do* modify the sample. Even in case of success, at
* least the type and uint value are modified.
*/
#define CHECK_HTTP_MESSAGE_FIRST(chn) \
do { int r = smp_prefetch_http(smp->px, smp->strm, smp->opt, (chn), smp, 1); if (r <= 0) return r; } while (0)
#define CHECK_HTTP_MESSAGE_FIRST_PERM(chn) \
do { int r = smp_prefetch_http(smp->px, smp->strm, smp->opt, (chn), smp, 0); if (r <= 0) return r; } while (0)
int smp_prefetch_http(struct proxy *px, struct stream *s, unsigned int opt,
struct channel *chn, struct sample *smp, int req_vol);
struct htx;
struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, int vol); struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, int vol);
int val_hdr(struct arg *arg, char **err_msg); int val_hdr(struct arg *arg, char **err_msg);

153
src/51d.c
View File

@ -227,63 +227,29 @@ static void _51d_retrieve_cache_entry(struct sample *smp, struct lru64 *lru)
*/ */
static void _51d_set_headers(struct sample *smp, fiftyoneDegreesWorkset *ws) static void _51d_set_headers(struct sample *smp, fiftyoneDegreesWorkset *ws)
{ {
struct channel *chn;
struct htx *htx;
struct http_hdr_ctx ctx;
struct ist name;
int i; int i;
ws->importantHeadersCount = 0; ws->importantHeadersCount = 0;
chn = (smp->strm ? &smp->strm->req : NULL);
if (smp->px->options2 & PR_O2_USE_HTX) { // No need to null check as this has already been carried out in the
/* HTX version */ // calling method
struct htx *htx; htx = smp_prefetch_htx(smp, chn, 1);
struct http_hdr_ctx ctx;
struct ist name;
struct channel *chn;
chn = (smp->strm ? &smp->strm->req : NULL); for (i = 0; i < global_51degrees.header_count; i++) {
name.ptr = (global_51degrees.header_names + i)->area;
name.len = (global_51degrees.header_names + i)->data;
ctx.blk = NULL;
// No need to null check as this has already been carried out in the if (http_find_header(htx, name, &ctx, 1)) {
// calling method ws->importantHeaders[ws->importantHeadersCount].header = ws->dataSet->httpHeaders + i;
htx = smp_prefetch_htx(smp, chn, 1); ws->importantHeaders[ws->importantHeadersCount].headerValue = ctx.value.ptr;
ws->importantHeaders[ws->importantHeadersCount].headerValueLength = ctx.value.len;
for (i = 0; i < global_51degrees.header_count; i++) { ws->importantHeadersCount++;
name.ptr = (global_51degrees.header_names + i)->area;
name.len = (global_51degrees.header_names + i)->data;
ctx.blk = NULL;
if (http_find_header(htx, name, &ctx, 1)) {
ws->importantHeaders[ws->importantHeadersCount].header = ws->dataSet->httpHeaders + i;
ws->importantHeaders[ws->importantHeadersCount].headerValue = ctx.value.ptr;
ws->importantHeaders[ws->importantHeadersCount].headerValueLength = ctx.value.len;
ws->importantHeadersCount++;
}
}
}
else {
/* Legacy Version */
struct hdr_idx *idx;
struct hdr_ctx ctx;
const struct http_msg *msg;
idx = &smp->strm->txn->hdr_idx;
msg = &smp->strm->txn->req;
for (i = 0; i < global_51degrees.header_count; i++) {
ctx.idx = 0;
if (http_find_full_header2((global_51degrees.header_names + i)->area,
(global_51degrees.header_names + i)->data,
#ifndef BUF_NULL
msg->chn->buf->p,
#else
ci_head(msg->chn),
#endif
idx,
&ctx) == 1) {
ws->importantHeaders[ws->importantHeadersCount].header = ws->dataSet->httpHeaders + i;
ws->importantHeaders[ws->importantHeadersCount].headerValue = ctx.line + ctx.val;
ws->importantHeaders[ws->importantHeadersCount].headerValueLength = ctx.vlen;
ws->importantHeadersCount++;
}
} }
} }
} }
@ -299,63 +265,31 @@ static void _51d_init_device_offsets(fiftyoneDegreesDeviceOffsets *offsets) {
static void _51d_set_device_offsets(struct sample *smp, fiftyoneDegreesDeviceOffsets *offsets) static void _51d_set_device_offsets(struct sample *smp, fiftyoneDegreesDeviceOffsets *offsets)
{ {
struct channel *chn;
struct htx *htx;
struct http_hdr_ctx ctx;
struct ist name;
int i; int i;
offsets->size = 0; offsets->size = 0;
chn = (smp->strm ? &smp->strm->req : NULL);
if (smp->px->options2 & PR_O2_USE_HTX) { // No need to null check as this has already been carried out in the
/* HTX version */ // calling method
struct htx *htx; htx = smp_prefetch_htx(smp, chn, 1);
struct http_hdr_ctx ctx;
struct ist name;
struct channel *chn;
chn = (smp->strm ? &smp->strm->req : NULL); for (i = 0; i < global_51degrees.header_count; i++) {
name.ptr = (global_51degrees.header_names + i)->area;
name.len = (global_51degrees.header_names + i)->data;
ctx.blk = NULL;
// No need to null check as this has already been carried out in the if (http_find_header(htx, name, &ctx, 1)) {
// calling method (offsets->firstOffset + offsets->size)->httpHeaderOffset = *(global_51degrees.header_offsets + i);
htx = smp_prefetch_htx(smp, chn, 1); (offsets->firstOffset + offsets->size)->deviceOffset = fiftyoneDegreesGetDeviceOffset(&global_51degrees.data_set, ctx.value.ptr);
offsets->size++;
for (i = 0; i < global_51degrees.header_count; i++) {
name.ptr = (global_51degrees.header_names + i)->area;
name.len = (global_51degrees.header_names + i)->data;
ctx.blk = NULL;
if (http_find_header(htx, name, &ctx, 1)) {
(offsets->firstOffset + offsets->size)->httpHeaderOffset = *(global_51degrees.header_offsets + i);
(offsets->firstOffset + offsets->size)->deviceOffset = fiftyoneDegreesGetDeviceOffset(&global_51degrees.data_set, ctx.value.ptr);
offsets->size++;
}
}
}
else {
/* Legacy Version */
struct hdr_idx *idx;
struct hdr_ctx ctx;
const struct http_msg *msg;
idx = &smp->strm->txn->hdr_idx;
msg = &smp->strm->txn->req;
for (i = 0; i < global_51degrees.header_count; i++) {
ctx.idx = 0;
if (http_find_full_header2((global_51degrees.header_names + i)->area,
(global_51degrees.header_names + i)->data,
#ifndef BUF_NULL
msg->chn->buf->p,
#else
ci_head(msg->chn),
#endif
idx,
&ctx) == 1) {
(offsets->firstOffset + offsets->size)->httpHeaderOffset = *(global_51degrees.header_offsets + i);
(offsets->firstOffset + offsets->size)->deviceOffset = fiftyoneDegreesGetDeviceOffset(&global_51degrees.data_set, ctx.line + ctx.val);
offsets->size++;
}
} }
} }
} }
#endif #endif
@ -472,18 +406,13 @@ static int _51d_fetch(const struct arg *args, struct sample *smp, const char *kw
#endif #endif
struct channel *chn; struct channel *chn;
chn = (smp->strm ? &smp->strm->req : NULL); struct htx *htx;
chn = (smp->strm ? &smp->strm->req : NULL);
htx = smp_prefetch_htx(smp, chn, 1);
if (!htx)
return 0;
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);
}
/* /*
* Data type has to be reset to ensure the string output is processed * Data type has to be reset to ensure the string output is processed
* correctly. * correctly.
@ -840,4 +769,4 @@ REGISTER_POST_DEINIT(deinit_51degrees);
#else #else
REGISTER_BUILD_OPTS("Built with 51Degrees Trie support (dummy library)."); REGISTER_BUILD_OPTS("Built with 51Degrees Trie support (dummy library).");
#endif #endif
#endif #endif

201
src/da.c
View File

@ -291,6 +291,8 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
da_deviceinfo_t devinfo; da_deviceinfo_t devinfo;
da_status_t status; da_status_t status;
struct channel *chn; struct channel *chn;
struct htx *htx;
struct htx_blk *blk;
char vbuf[DA_MAX_HEADERS][1024] = {{ 0 }}; char vbuf[DA_MAX_HEADERS][1024] = {{ 0 }};
int i, nbh = 0; int i, nbh = 0;
@ -299,152 +301,79 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
} }
chn = (smp->strm ? &smp->strm->req : NULL); chn = (smp->strm ? &smp->strm->req : NULL);
/* HTX Mode check */ htx = smp_prefetch_htx(smp, chn, 1);
if (smp->px->options2 & PR_O2_USE_HTX) { if (!htx)
struct htx_blk *blk; return 0;
struct htx *htx = smp_prefetch_htx(smp, chn, 1);
if (!htx) { i = 0;
return 0; for (blk = htx_get_first_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 };
type = htx_get_blk_type(blk);
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;
} }
i = 0; /* The HTTP headers used by the DeviceAtlas API are not longer */
for (blk = htx_get_first_blk(htx); nbh < DA_MAX_HEADERS && blk; blk = htx_get_next_blk(htx, blk)) { if (n.len >= sizeof(hbuf)) {
size_t vlen; continue;
char *pval;
da_evidence_id_t evid;
enum htx_blk_type type;
struct ist n, v;
char hbuf[24] = { 0 };
char tval[1024] = { 0 };
type = htx_get_blk_type(blk);
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;
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;
}
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);
}
if (evid == -1) {
continue;
}
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;
/** memcpy(hbuf, n.ptr, n.len);
* Here we go through the whole list of headers from start hbuf[n.len] = 0;
* they will be filtered via the DeviceAtlas API itself pval = v.ptr;
*/ vlen = v.len;
hctx.idx = 0; evid = -1;
hidx = &smp->strm->txn->hdr_idx; i = v.len > sizeof(tval) - 1 ? sizeof(tval) - 1 : v.len;
hmsg = &smp->strm->txn->req; memcpy(tval, v.ptr, i);
tval[i] = 0;
pval = tval;
while (http_find_next_header(ci_head(hmsg->chn), hidx, &hctx) == 1 && if (strcasecmp(hbuf, "Accept-Language") == 0) {
nbh < DA_MAX_HEADERS) { evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.atlas);
char *pval; } else if (strcasecmp(hbuf, "Cookie") == 0) {
size_t vlen; char *p, *eval;
da_evidence_id_t evid = -1; size_t pl;
char hbuf[24] = { 0 };
/* The HTTP headers used by the DeviceAtlas API are not longer */ eval = pval + vlen;
if (hctx.del >= sizeof(hbuf) || hctx.del <= 0 || hctx.vlen <= 0) { /**
* 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; continue;
} }
vlen = hctx.vlen; vlen -= global_deviceatlas.cookienamelen - 1;
memcpy(hbuf, hctx.line, hctx.del); pval = p;
hbuf[hctx.del] = 0; evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
pval = (hctx.line + hctx.val); } else {
evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas, hbuf);
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;
} }
if (evid == -1) {
continue;
}
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;
} }
status = da_searchv(&global_deviceatlas.atlas, &devinfo, status = da_searchv(&global_deviceatlas.atlas, &devinfo,

File diff suppressed because it is too large Load Diff

View File

@ -431,23 +431,14 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
wurfl_information_t *wi; wurfl_information_t *wi;
ha_wurfl_header_t wh; ha_wurfl_header_t wh;
struct channel *chn; struct channel *chn;
struct htx *htx;
ha_wurfl_log("WURFL: starting ha_wurfl_get_all\n"); ha_wurfl_log("WURFL: starting ha_wurfl_get_all\n");
chn = (smp->strm ? &smp->strm->req : NULL); chn = (smp->strm ? &smp->strm->req : NULL);
htx = smp_prefetch_htx(smp, chn, 1);
if (smp->px->options2 & PR_O2_USE_HTX) { if (!htx)
/* HTX version */ return 0;
struct htx *htx = smp_prefetch_htx(smp, chn, 1);
if (!htx) {
return 0;
}
} else {
/* Legacy version */
CHECK_HTTP_MESSAGE_FIRST(chn);
}
wh.wsmp = smp; wh.wsmp = smp;
@ -526,23 +517,14 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
ha_wurfl_header_t wh; ha_wurfl_header_t wh;
int i = 0; int i = 0;
struct channel *chn; struct channel *chn;
struct htx *htx;
ha_wurfl_log("WURFL: starting ha_wurfl_get\n"); ha_wurfl_log("WURFL: starting ha_wurfl_get\n");
chn = (smp->strm ? &smp->strm->req : NULL); chn = (smp->strm ? &smp->strm->req : NULL);
htx = smp_prefetch_htx(smp, chn, 1);
if (smp->px->options2 & PR_O2_USE_HTX) { if (!htx)
/* HTX version */ return 0;
struct htx *htx = smp_prefetch_htx(smp, chn, 1);
if (!htx) {
return 0;
}
} else {
/* Legacy version */
CHECK_HTTP_MESSAGE_FIRST(chn);
}
wh.wsmp = smp; wh.wsmp = smp;
@ -741,77 +723,41 @@ static const char *ha_wurfl_retrieve_header(const char *header_name, const void
{ {
struct sample *smp; struct sample *smp;
struct channel *chn; struct channel *chn;
struct htx *htx;
struct http_hdr_ctx ctx;
struct ist name;
int header_len = HA_WURFL_MAX_HEADER_LENGTH; int header_len = HA_WURFL_MAX_HEADER_LENGTH;
smp = ((ha_wurfl_header_t *)wh)->wsmp; smp = ((ha_wurfl_header_t *)wh)->wsmp;
chn = (smp->strm ? &smp->strm->req : NULL); chn = (smp->strm ? &smp->strm->req : NULL);
if (smp->px->options2 & PR_O2_USE_HTX) { ha_wurfl_log("WURFL: retrieve header (HTX) request [%s]\n", header_name);
/* HTX version */
struct htx *htx;
struct http_hdr_ctx ctx;
struct ist name;
ha_wurfl_log("WURFL: retrieve header (HTX) request [%s]\n", header_name); //the header is searched from the beginning
ctx.blk = NULL;
//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);
// 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);
((ha_wurfl_header_t *)wh)->header_value[header_len] = '\0'; ((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); ha_wurfl_log("WURFL: retrieve header request returns [%s]\n", ((ha_wurfl_header_t *)wh)->header_value);