]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http: add body_param fetch
authorThierry FOURNIER <tfournier@haproxy.com>
Tue, 19 May 2015 12:45:09 +0000 (14:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 20 May 2015 13:56:23 +0000 (15:56 +0200)
This fetch returns one body param or the list of each body param.
This first version runs only with one chunk.

src/proto_http.c

index d3c7fa7a397150033459f6c6dd34196ffff016b7..33a35681b4ea843eaf65cc7882cd9220c2ee70b8 100644 (file)
@@ -11651,6 +11651,62 @@ smp_fetch_url_param(const struct arg *args, struct sample *smp, const char *kw,
        return smp_fetch_param(delim, name, name_len, args, smp, kw, private);
 }
 
+/* This function iterates over each parameter of the body. This requires
+ * that the body has been waited for using http-buffer-request. It uses
+ * ctx->a[0] and ctx->a[1] to store the beginning and end of the current
+ * parameter. An optional parameter name is passed in args[0], otherwise
+ * any parameter is considered.
+ */
+static int
+smp_fetch_body_param(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       struct http_txn *txn = smp->strm->txn;
+       struct http_msg *msg;
+       unsigned long len;
+       unsigned long block1;
+       char *body;
+       const char *name;
+       int name_len;
+
+       if (!args || (args[0].type && args[0].type != ARGT_STR))
+               return 0;
+
+       name = "";
+       name_len = 0;
+       if (args[0].type == ARGT_STR) {
+               name     = args[0].data.str.str;
+               name_len = args[0].data.str.len;
+       }
+
+       if (!smp->ctx.a[0]) { // first call, find the query string
+               CHECK_HTTP_MESSAGE_FIRST();
+
+               if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ)
+                       msg = &txn->req;
+               else
+                       msg = &txn->rsp;
+
+               len  = http_body_bytes(msg);
+               body = b_ptr(msg->chn->buf, -http_data_rewind(msg));
+
+               block1 = len;
+               if (block1 > msg->chn->buf->data + msg->chn->buf->size - body)
+                       block1 = msg->chn->buf->data + msg->chn->buf->size - body;
+
+               if (block1 == len) {
+                       /* buffer is not wrapped (or empty) */
+                       smp->ctx.a[0] = body;
+                       smp->ctx.a[1] = body + len;
+               }
+               else {
+                       /* buffer is wrapped, we need to defragment it */
+                       smp->ctx.a[0] = body;
+                       smp->ctx.a[1] = body + block1;
+               }
+       }
+       return smp_fetch_param('&', name, name_len, args, smp, kw, private);
+}
+
 /* Return the signed integer value for the specified url parameter (see url_param
  * above).
  */
@@ -12471,6 +12527,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "req.body",        smp_fetch_body,           0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
        { "req.body_len",    smp_fetch_body_len,       0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
        { "req.body_size",   smp_fetch_body_size,      0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+       { "req.body_param",  smp_fetch_body_param,     ARG1(0,STR),      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 },