]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stats: Get the right scope pointer depending on HTX is used or not
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 14 Jan 2019 10:07:34 +0000 (11:07 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Jan 2019 16:27:49 +0000 (17:27 +0100)
For HTX streams, the scope pointer is relative to the URI in the start-line. But
for streams using the legacy HTTP representation, the scope pointer is relative
to the beginning of output data in the channel's buffer. So we must be careful
to use the right one depending on the HTX is used or not.

Because the start-line is used to get de scope pointer, it is important to keep
it after the parsing of post paramters. So now, instead of removing blocks when
read in the function stats_process_http_post(), we just move on next, leaving it
in the HTX message.

Thanks to Pieter (PiBa-NL) to report this bug.

This patch must be backported to 1.9.

src/proto_htx.c
src/stats.c

index 236bfd04d56aca225190ce3afdd0e13b081421f9..9fa82065396296606a2b8285b0a481e826c3ba37 100644 (file)
@@ -4887,8 +4887,8 @@ static int htx_handle_stats(struct stream *s, struct channel *req)
 
                        h += strlen(STAT_SCOPE_INPUT_NAME) + 1;
                        h2 = h;
-                       appctx->ctx.stats.scope_str = h2 - s->txn->uri;
-                       while (h <= end) {
+                       appctx->ctx.stats.scope_str = h2 - HTX_SL_REQ_UPTR(sl);
+                       while (h < end) {
                                if (*h == ';' || *h == '&' || *h == ' ')
                                        break;
                                itx++;
index ebd95d3f04fc2094fd36b5ea95c0670436f0c680..a7c12e1201d83046ff64d4014d2f51c701f52ea6 100644 (file)
@@ -55,6 +55,7 @@
 #include <proto/fd.h>
 #include <proto/freq_ctr.h>
 #include <proto/frontend.h>
+#include <proto/http_htx.h>
 #include <proto/log.h>
 #include <proto/pattern.h>
 #include <proto/pipe.h>
@@ -257,6 +258,23 @@ static int stats_putchk(struct channel *chn, struct htx *htx, struct buffer *chk
        return 1;
 }
 
+static const char *stats_scope_ptr(struct appctx *appctx, struct stream_interface *si)
+{
+       const char *p;
+
+       if (IS_HTX_STRM(si_strm(si))) {
+               struct channel *req = si_oc(si);
+               struct htx *htx = htxbuf(&req->buf);
+               struct ist uri = htx_sl_req_uri(http_find_stline(htx));
+
+               p = uri.ptr;
+       }
+       else
+               p = co_head(si_oc(si));
+
+       return p + appctx->ctx.stats.scope_str;
+}
+
 /*
  * http_stats_io_handler()
  *     -> stats_dump_stat_to_buffer()     // same as above, but used for CSV or HTML
@@ -1912,8 +1930,10 @@ static void stats_dump_html_px_hdr(struct stream_interface *si, struct proxy *px
                /* scope_txt = search pattern + search query, appctx->ctx.stats.scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
                scope_txt[0] = 0;
                if (appctx->ctx.stats.scope_len) {
+                       const char *scope_ptr = stats_scope_ptr(appctx, si);
+
                        strcpy(scope_txt, STAT_SCOPE_PATTERN);
-                       memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), co_head(si_oc(si)) + appctx->ctx.stats.scope_str, appctx->ctx.stats.scope_len);
+                       memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), scope_ptr, appctx->ctx.stats.scope_len);
                        scope_txt[strlen(STAT_SCOPE_PATTERN) + appctx->ctx.stats.scope_len] = 0;
                }
 
@@ -2075,9 +2095,12 @@ int stats_dump_proxy_to_buffer(struct stream_interface *si, struct htx *htx,
                /* if the user has requested a limited output and the proxy
                 * name does not match, skip it.
                 */
-               if (appctx->ctx.stats.scope_len &&
-                   strnistr(px->id, strlen(px->id), co_head(si_oc(si)) + appctx->ctx.stats.scope_str, appctx->ctx.stats.scope_len) == NULL)
-                       return 1;
+               if (appctx->ctx.stats.scope_len) {
+                       const char *scope_ptr = stats_scope_ptr(appctx, si);
+
+                       if (strnistr(px->id, strlen(px->id), scope_ptr, appctx->ctx.stats.scope_len) == NULL)
+                               return 1;
+               }
 
                if ((appctx->ctx.stats.flags & STAT_BOUND) &&
                    (appctx->ctx.stats.iid != -1) &&
@@ -2347,6 +2370,7 @@ static void stats_dump_html_info(struct stream_interface *si, struct uri_auth *u
        struct appctx *appctx = __objt_appctx(si->end);
        unsigned int up = (now.tv_sec - start_date.tv_sec);
        char scope_txt[STAT_SCOPE_TXT_MAXLEN + sizeof STAT_SCOPE_PATTERN];
+       const char *scope_ptr = stats_scope_ptr(appctx, si);
 
        /* WARNING! this has to fit the first packet too.
         * We are around 3.5 kB, add adding entries will
@@ -2405,7 +2429,7 @@ static void stats_dump_html_info(struct stream_interface *si, struct uri_auth *u
                      );
 
        /* scope_txt = search query, appctx->ctx.stats.scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
-       memcpy(scope_txt, co_head(si_oc(si)) + appctx->ctx.stats.scope_str, appctx->ctx.stats.scope_len);
+       memcpy(scope_txt, scope_ptr, appctx->ctx.stats.scope_len);
        scope_txt[appctx->ctx.stats.scope_len] = '\0';
 
        chunk_appendf(&trash,
@@ -2417,7 +2441,7 @@ static void stats_dump_html_info(struct stream_interface *si, struct uri_auth *u
        scope_txt[0] = 0;
        if (appctx->ctx.stats.scope_len) {
                strcpy(scope_txt, STAT_SCOPE_PATTERN);
-               memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), co_head(si_oc(si)) + appctx->ctx.stats.scope_str, appctx->ctx.stats.scope_len);
+               memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), scope_ptr, appctx->ctx.stats.scope_len);
                scope_txt[strlen(STAT_SCOPE_PATTERN) + appctx->ctx.stats.scope_len] = 0;
        }
 
@@ -2719,7 +2743,13 @@ static int stats_process_http_post(struct stream_interface *si)
                struct htx_blk *blk;
                size_t count = co_data(&s->req);
 
-               /* Remove the headers */
+               /* we need more data */
+               if (htx->extra || htx->data > count) {
+                       appctx->ctx.stats.st_code = STAT_STATUS_NONE;
+                       return 0;
+               }
+
+               /* Skip the headers */
                blk = htx_get_head_blk(htx);
                while (count && blk) {
                        enum htx_blk_type type = htx_get_blk_type(blk);
@@ -2731,25 +2761,18 @@ static int stats_process_http_post(struct stream_interface *si)
                        }
 
                        count -= sz;
-                       co_set_data(&s->req, co_data(&s->req) - sz);
-                       blk = htx_remove_blk(htx, blk);
+                       blk = htx_get_next_blk(htx, blk);
 
                        if (type == HTX_BLK_EOH)
                                break;
                }
 
                /* too large request */
-               if (htx->data + htx->extra > b_size(temp)) {
+               if (count > b_size(temp)) {
                        appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
                        goto out;
                }
 
-               /* we need more data */
-               if (htx->extra || htx->data > count) {
-                       appctx->ctx.stats.st_code = STAT_STATUS_NONE;
-                       return 0;
-               }
-
                while (count && blk) {
                        enum htx_blk_type type = htx_get_blk_type(blk);
                        uint32_t sz = htx_get_blksz(blk);
@@ -2766,8 +2789,7 @@ static int stats_process_http_post(struct stream_interface *si)
                        }
 
                        count -= sz;
-                       co_set_data(&s->req, co_data(&s->req) - sz);
-                       blk = htx_remove_blk(htx, blk);
+                       blk = htx_get_next_blk(htx, blk);
                }
        }
        else {
@@ -3135,8 +3157,10 @@ static int stats_send_htx_redirect(struct stream_interface *si, struct htx *htx)
        /* scope_txt = search pattern + search query, appctx->ctx.stats.scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
        scope_txt[0] = 0;
        if (appctx->ctx.stats.scope_len) {
+               const char *scope_ptr = stats_scope_ptr(appctx, si);
+
                strcpy(scope_txt, STAT_SCOPE_PATTERN);
-               memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), co_head(si_oc(si)) + appctx->ctx.stats.scope_str, appctx->ctx.stats.scope_len);
+               memcpy(scope_txt + strlen(STAT_SCOPE_PATTERN), scope_ptr, appctx->ctx.stats.scope_len);
                scope_txt[strlen(STAT_SCOPE_PATTERN) + appctx->ctx.stats.scope_len] = 0;
        }