BUG/MINOR: 51d/htx: The _51d_fetch method, and the methods it calls are now HTX aware.

The _51d_fetch method, and the two methods it calls to fetch HTTP
headers (_51d_set_device_offsets, and _51d_set_headers), now support
both legacy and HTX operation.

This should be backported to 1.9.
This commit is contained in:
Ben51Degrees 2019-06-12 15:19:12 +01:00 committed by Willy Tarreau
parent 3381022d88
commit 31a51f25d6

159
src/51d.c
View File

@ -9,6 +9,7 @@
#include <types/global.h> #include <types/global.h>
#include <proto/arg.h> #include <proto/arg.h>
#include <proto/http_fetch.h> #include <proto/http_fetch.h>
#include <proto/http_htx.h>
#include <proto/log.h> #include <proto/log.h>
#include <proto/proto_http.h> #include <proto/proto_http.h>
#include <proto/sample.h> #include <proto/sample.h>
@ -226,31 +227,63 @@ 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 hdr_idx *idx;
struct hdr_ctx ctx;
const struct http_msg *msg;
int i; int i;
idx = &smp->strm->txn->hdr_idx;
msg = &smp->strm->txn->req;
ws->importantHeadersCount = 0; ws->importantHeadersCount = 0;
for (i = 0; i < global_51degrees.header_count; i++) { if (smp->px->options2 & PR_O2_USE_HTX) {
ctx.idx = 0; /* HTX version */
if (http_find_full_header2((global_51degrees.header_names + i)->area, struct htx *htx;
(global_51degrees.header_names + i)->data, struct http_hdr_ctx ctx;
struct ist name;
struct channel *chn;
chn = (smp->strm ? &smp->strm->req : NULL);
// No need to null check as this has already been carried out in the
// calling method
htx = smp_prefetch_htx(smp, chn, 1);
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)) {
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 #ifndef BUF_NULL
msg->chn->buf->p, msg->chn->buf->p,
#else #else
ci_head(msg->chn), ci_head(msg->chn),
#endif #endif
idx, idx,
&ctx) == 1) { &ctx) == 1) {
ws->importantHeaders[ws->importantHeadersCount].header = ws->dataSet->httpHeaders + i; ws->importantHeaders[ws->importantHeadersCount].header = ws->dataSet->httpHeaders + i;
ws->importantHeaders[ws->importantHeadersCount].headerValue = ctx.line + ctx.val; ws->importantHeaders[ws->importantHeadersCount].headerValue = ctx.line + ctx.val;
ws->importantHeaders[ws->importantHeadersCount].headerValueLength = ctx.vlen; ws->importantHeaders[ws->importantHeadersCount].headerValueLength = ctx.vlen;
ws->importantHeadersCount++; ws->importantHeadersCount++;
}
} }
} }
} }
@ -266,30 +299,61 @@ 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 hdr_idx *idx; int i;
struct hdr_ctx ctx;
const struct http_msg *msg;
int index;
idx = &smp->strm->txn->hdr_idx;
msg = &smp->strm->txn->req;
offsets->size = 0; offsets->size = 0;
for (index = 0; index < global_51degrees.header_count; index++) { if (smp->px->options2 & PR_O2_USE_HTX) {
ctx.idx = 0; /* HTX version */
if (http_find_full_header2((global_51degrees.header_names + index)->area, struct htx *htx;
(global_51degrees.header_names + index)->data, struct http_hdr_ctx ctx;
#ifndef BUF_NULL struct ist name;
msg->chn->buf->p, struct channel *chn;
#else
ci_head(msg->chn),
#endif
idx,
&ctx) == 1) {
(offsets->firstOffset + offsets->size)->httpHeaderOffset = *(global_51degrees.header_offsets + index); chn = (smp->strm ? &smp->strm->req : NULL);
(offsets->firstOffset + offsets->size)->deviceOffset = fiftyoneDegreesGetDeviceOffset(&global_51degrees.data_set, ctx.line + ctx.val);
offsets->size++; // No need to null check as this has already been carried out in the
// calling method
htx = smp_prefetch_htx(smp, chn, 1);
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++;
}
} }
} }
} }
@ -405,14 +469,25 @@ static int _51d_fetch(const struct arg *args, struct sample *smp, const char *kw
#endif #endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED #ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
fiftyoneDegreesDeviceOffsets *offsets; /* Offsets for detection */ fiftyoneDegreesDeviceOffsets *offsets; /* Offsets for detection */
#endif
/* Needed to ensure that the HTTP message has been fully received when #endif
* used with TCP operation. Not required for HTTP operation. struct channel *chn;
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);
}
/*
* 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.
*/ */
CHECK_HTTP_MESSAGE_FIRST((smp->strm ? &smp->strm->req : NULL));
smp->data.type = SMP_T_STR; smp->data.type = SMP_T_STR;
/* Flags the sample to show it uses constant memory*/ /* Flags the sample to show it uses constant memory*/