mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-24 20:07:33 +00:00
MINOR: Add binary encoding request header sample fetch
This sample fetch encodes the http request headers in binary format. This sample-fetch is useful with SPOE.
This commit is contained in:
parent
6ab2bae084
commit
5617dce27d
@ -14167,6 +14167,19 @@ payload_lv(<offset1>,<length>[,<offset2>]) : binary (deprecated)
|
||||
(eg: "stick on", "stick match"), and for "res.payload_lv" when used in the
|
||||
context of a response such as in "stick store response".
|
||||
|
||||
req.hdrs_bin : binary
|
||||
Returns the current request headers contained in preparsed binary form. This
|
||||
is useful for offloading some processing with SPOE. Each string is described
|
||||
by a length followed by the number of bytes indicated in the length. The
|
||||
length is represented using the variable integer encoding detailed in the
|
||||
SPOE documentation. The end of the list is marked by a couple of empty header
|
||||
names and values (length of 0 for both).
|
||||
|
||||
*(<str:header-name><str:header-value>)<empty string><empty string>
|
||||
|
||||
int: refer to the SPOE documentation for the encoding
|
||||
str: <int:length><bytes>
|
||||
|
||||
req.len : integer
|
||||
req_len : integer (deprecated)
|
||||
Returns an integer value corresponding to the number of bytes present in the
|
||||
|
112
src/proto_http.c
112
src/proto_http.c
@ -10437,6 +10437,116 @@ smp_fetch_uniqueid(const struct arg *args, struct sample *smp, const char *kw, v
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns the header request in a length/value encoded format.
|
||||
* This is useful for exchanges with the SPOE.
|
||||
*
|
||||
* A "length value" is a multibyte code encoding numbers. It uses the
|
||||
* SPOE format. The encoding is the following:
|
||||
*
|
||||
* Each couple "header name" / "header value" is composed
|
||||
* like this:
|
||||
* "length value" "header name bytes"
|
||||
* "length value" "header value bytes"
|
||||
* When the last header is reached, the header name and the header
|
||||
* value are empty. Their length are 0
|
||||
*/
|
||||
static int
|
||||
smp_fetch_hdrs_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
struct http_msg *msg;
|
||||
struct chunk *temp;
|
||||
struct hdr_idx *idx;
|
||||
const char *cur_ptr, *cur_next, *p;
|
||||
int old_idx, cur_idx;
|
||||
struct hdr_idx_elem *cur_hdr;
|
||||
const char *hn, *hv;
|
||||
int hnl, hvl;
|
||||
int ret;
|
||||
struct http_txn *txn;
|
||||
char *buf;
|
||||
char *end;
|
||||
|
||||
CHECK_HTTP_MESSAGE_FIRST();
|
||||
|
||||
temp = get_trash_chunk();
|
||||
buf = temp->str;
|
||||
end = temp->str + temp->size;
|
||||
|
||||
txn = smp->strm->txn;
|
||||
idx = &txn->hdr_idx;
|
||||
msg = &txn->req;
|
||||
|
||||
/* Build array of headers. */
|
||||
old_idx = 0;
|
||||
cur_next = msg->chn->buf->p + hdr_idx_first_pos(idx);
|
||||
while (1) {
|
||||
cur_idx = idx->v[old_idx].next;
|
||||
if (!cur_idx)
|
||||
break;
|
||||
old_idx = cur_idx;
|
||||
|
||||
cur_hdr = &idx->v[cur_idx];
|
||||
cur_ptr = cur_next;
|
||||
cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
|
||||
|
||||
/* Now we have one full header at cur_ptr of len cur_hdr->len,
|
||||
* and the next header starts at cur_next. We'll check
|
||||
* this header in the list as well as against the default
|
||||
* rule.
|
||||
*/
|
||||
|
||||
/* look for ': *'. */
|
||||
hn = cur_ptr;
|
||||
for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
|
||||
if (p >= cur_ptr+cur_hdr->len)
|
||||
continue;
|
||||
hnl = p - hn;
|
||||
p++;
|
||||
while (p < cur_ptr + cur_hdr->len && (*p == ' ' || *p == '\t'))
|
||||
p++;
|
||||
if (p >= cur_ptr + cur_hdr->len)
|
||||
continue;
|
||||
hv = p;
|
||||
hvl = cur_ptr + cur_hdr->len-p;
|
||||
|
||||
/* encode the header name. */
|
||||
ret = encode_varint(hnl, &buf, end);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
if (buf + hnl > end)
|
||||
return 0;
|
||||
memcpy(buf, hn, hnl);
|
||||
buf += hnl;
|
||||
|
||||
/* encode and copy the value. */
|
||||
ret = encode_varint(hvl, &buf, end);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
if (buf + hvl > end)
|
||||
return 0;
|
||||
memcpy(buf, hv, hvl);
|
||||
buf += hvl;
|
||||
}
|
||||
|
||||
/* encode the end of the header list with empty
|
||||
* header name and header value.
|
||||
*/
|
||||
ret = encode_varint(0, &buf, end);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
ret = encode_varint(0, &buf, end);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
|
||||
/* Initialise sample data which will be filled. */
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.str = temp->str;
|
||||
smp->data.u.str.len = buf - temp->str;
|
||||
smp->data.u.str.size = temp->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* returns the longest available part of the body. This requires that the body
|
||||
* has been waited for using http-buffer-request.
|
||||
*/
|
||||
@ -13347,6 +13457,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
|
||||
{ "req.body_size", smp_fetch_body_size, 0, NULL, SMP_T_SINT, SMP_USE_HRQHV },
|
||||
{ "req.body_param", smp_fetch_body_param, ARG1(0,STR), NULL, SMP_T_BIN, SMP_USE_HRQHV },
|
||||
|
||||
{ "req.hdrs_bin", smp_fetch_hdrs_bin, 0, NULL, SMP_T_BIN, SMP_USE_HRQHV },
|
||||
|
||||
/* HTTP version on the response path */
|
||||
{ "res.ver", smp_fetch_stver, 0, NULL, SMP_T_STR, SMP_USE_HRSHV },
|
||||
{ "resp_ver", smp_fetch_stver, 0, NULL, SMP_T_STR, SMP_USE_HRSHV },
|
||||
|
Loading…
Reference in New Issue
Block a user