]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats: Remove code relying on the legacy HTTP mode
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 15 Jul 2019 19:56:43 +0000 (21:56 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 19 Jul 2019 07:18:27 +0000 (09:18 +0200)
The part of the applet dealing with raw buffer was removed, for the HTTP part
only. So the old functions stats_send_http_headers() and
stats_send_http_redirect() were removed and replaced by the htx ones. The legacy
applet I/O handler was replaced by the htx one. And the parsing of POST data was
purged of the legacy HTTP code.

src/stats.c

index d40e0890cc4e8488832f633117fc09c682a841c6..6744163242ec955e0ec9c70b9aac8c8801341eb6 100644 (file)
@@ -62,7 +62,6 @@
 #include <proto/pipe.h>
 #include <proto/listener.h>
 #include <proto/map.h>
-#include <proto/proto_http.h>
 #include <proto/proxy.h>
 #include <proto/sample.h>
 #include <proto/session.h>
@@ -272,24 +271,16 @@ static int stats_putchk(struct channel *chn, struct htx *htx, struct buffer *chk
 
 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 htx_blk *blk;
-               struct ist uri;
-
-               blk = htx_get_head_blk(htx);
-               BUG_ON(htx_get_blk_type(blk) != HTX_BLK_REQ_SL);
-               ALREADY_CHECKED(blk);
-               uri = htx_sl_req_uri(htx_get_blk_ptr(htx, blk));
-               p = uri.ptr;
-       }
-       else
-               p = co_head(si_oc(si));
-
-       return p + appctx->ctx.stats.scope_str;
+       struct channel *req = si_oc(si);
+       struct htx *htx = htxbuf(&req->buf);
+       struct htx_blk *blk;
+       struct ist uri;
+
+       blk = htx_get_head_blk(htx);
+       BUG_ON(htx_get_blk_type(blk) != HTX_BLK_REQ_SL);
+       ALREADY_CHECKED(blk);
+       uri = htx_sl_req_uri(htx_get_blk_ptr(htx, blk));
+       return uri.ptr + appctx->ctx.stats.scope_str;
 }
 
 /*
@@ -2778,57 +2769,35 @@ static int stats_process_http_post(struct stream_interface *si)
 
        struct buffer *temp = get_trash_chunk();
 
-       if (IS_HTX_STRM(s)) {
-               struct htx *htx = htxbuf(&s->req.buf);
-               struct htx_blk *blk;
+       struct htx *htx = htxbuf(&s->req.buf);
+       struct htx_blk *blk;
 
-               /*  we need more data */
-               if (s->txn->req.msg_state < HTTP_MSG_DONE) {
-                       /* check if we can receive more */
-                       if (htx_free_data_space(htx) <= global.tune.maxrewrite) {
-                               appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
-                               goto out;
-                       }
-                       goto wait;
+       /*  we need more data */
+       if (s->txn->req.msg_state < HTTP_MSG_DONE) {
+               /* check if we can receive more */
+               if (htx_free_data_space(htx) <= global.tune.maxrewrite) {
+                       appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
+                       goto out;
                }
+               goto wait;
+       }
 
-               /* The request was fully received. Copy data */
-               blk = htx_get_head_blk(htx);
-               while (blk) {
-                       enum htx_blk_type type = htx_get_blk_type(blk);
+       /* The request was fully received. Copy data */
+       blk = htx_get_head_blk(htx);
+       while (blk) {
+               enum htx_blk_type type = htx_get_blk_type(blk);
 
-                       if (type == HTX_BLK_EOM || type == HTX_BLK_TLR || type == HTX_BLK_EOT)
-                               break;
-                       if (type == HTX_BLK_DATA) {
-                               struct ist v = htx_get_blk_value(htx, blk);
-
-                               if (!chunk_memcat(temp, v.ptr, v.len)) {
-                                       appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
-                                       goto out;
-                               }
-                       }
-                       blk = htx_get_next_blk(htx, blk);
-               }
-       }
-       else {
-               int reql;
+               if (type == HTX_BLK_EOM || type == HTX_BLK_TLR || type == HTX_BLK_EOT)
+                       break;
+               if (type == HTX_BLK_DATA) {
+                       struct ist v = htx_get_blk_value(htx, blk);
 
-               /* we need more data */
-               if (s->txn->req.msg_state < HTTP_MSG_DONE) {
-                       /* check if we can receive more */
-                       if (c_room(&s->req) <= global.tune.maxrewrite) {
+                       if (!chunk_memcat(temp, v.ptr, v.len)) {
                                appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
                                goto out;
                        }
-                       goto wait;
                }
-               reql = co_getblk(si_oc(si), temp->area, s->txn->req.body_len,
-                                s->txn->req.eoh + 2);
-               if (reql <= 0) {
-                       appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
-                       goto out;
-               }
-               temp->data = reql;
+               blk = htx_get_next_blk(htx, blk);
        }
 
        first_param = temp->area;
@@ -3119,7 +3088,7 @@ static int stats_process_http_post(struct stream_interface *si)
 }
 
 
-static int stats_send_htx_headers(struct stream_interface *si, struct htx *htx)
+static int stats_send_http_headers(struct stream_interface *si, struct htx *htx)
 {
        struct stream *s = si_strm(si);
        struct uri_auth *uri = s->be->uri_auth;
@@ -3168,7 +3137,7 @@ static int stats_send_htx_headers(struct stream_interface *si, struct htx *htx)
 }
 
 
-static int stats_send_htx_redirect(struct stream_interface *si, struct htx *htx)
+static int stats_send_http_redirect(struct stream_interface *si, struct htx *htx)
 {
        char scope_txt[STAT_SCOPE_TXT_MAXLEN + sizeof STAT_SCOPE_PATTERN];
        struct stream *s = si_strm(si);
@@ -3226,90 +3195,13 @@ full:
        return 0;
 }
 
-static int stats_send_http_headers(struct stream_interface *si)
-{
-       struct stream *s = si_strm(si);
-       struct uri_auth *uri = s->be->uri_auth;
-       struct appctx *appctx = __objt_appctx(si->end);
-
-       chunk_printf(&trash,
-                    "HTTP/1.1 200 OK\r\n"
-                    "Cache-Control: no-cache\r\n"
-                    "Connection: close\r\n"
-                    "Content-Type: %s\r\n",
-                    (appctx->ctx.stats.flags & STAT_FMT_HTML) ? "text/html" : "text/plain");
-
-       if (uri->refresh > 0 && !(appctx->ctx.stats.flags & STAT_NO_REFRESH))
-               chunk_appendf(&trash, "Refresh: %d\r\n",
-                             uri->refresh);
-
-       /* we don't send the CRLF in chunked mode, it will be sent with the first chunk's size */
-
-       if (appctx->ctx.stats.flags & STAT_CHUNKED)
-               chunk_appendf(&trash, "Transfer-Encoding: chunked\r\n");
-       else
-               chunk_appendf(&trash, "\r\n");
-
-       if (ci_putchk(si_ic(si), &trash) == -1) {
-               si_rx_room_blk(si);
-               return 0;
-       }
-
-       return 1;
-}
-
-static int stats_send_http_redirect(struct stream_interface *si)
-{
-       char scope_txt[STAT_SCOPE_TXT_MAXLEN + sizeof STAT_SCOPE_PATTERN];
-       struct stream *s = si_strm(si);
-       struct uri_auth *uri = s->be->uri_auth;
-       struct appctx *appctx = __objt_appctx(si->end);
-
-       /* 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) {
-               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);
-               scope_txt[strlen(STAT_SCOPE_PATTERN) + appctx->ctx.stats.scope_len] = 0;
-       }
-
-       /* We don't want to land on the posted stats page because a refresh will
-        * repost the data. We don't want this to happen on accident so we redirect
-        * the browse to the stats page with a GET.
-        */
-       chunk_printf(&trash,
-                    "HTTP/1.1 303 See Other\r\n"
-                    "Cache-Control: no-cache\r\n"
-                    "Content-Type: text/plain\r\n"
-                    "Connection: close\r\n"
-                    "Location: %s;st=%s%s%s%s\r\n"
-                    "Content-length: 0\r\n"
-                    "\r\n",
-                    uri->uri_prefix,
-                    ((appctx->ctx.stats.st_code > STAT_STATUS_INIT) &&
-                     (appctx->ctx.stats.st_code < STAT_STATUS_SIZE) &&
-                     stat_status_codes[appctx->ctx.stats.st_code]) ?
-                    stat_status_codes[appctx->ctx.stats.st_code] :
-                    stat_status_codes[STAT_STATUS_UNKN],
-                    (appctx->ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "",
-                    (appctx->ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : "",
-                    scope_txt);
-
-       if (ci_putchk(si_ic(si), &trash) == -1) {
-               si_rx_room_blk(si);
-               return 0;
-       }
-
-       return 1;
-}
-
 
 /* This I/O handler runs as an applet embedded in a stream interface. It is
  * used to send HTTP stats over a TCP socket. The mechanism is very simple.
  * appctx->st0 contains the operation in progress (dump, done). The handler
  * automatically unregisters itself once transfer is complete.
  */
-static void htx_stats_io_handler(struct appctx *appctx)
+static void http_stats_io_handler(struct appctx *appctx)
 {
        struct stream_interface *si = appctx->owner;
        struct stream *s = si_strm(si);
@@ -3334,7 +3226,7 @@ static void htx_stats_io_handler(struct appctx *appctx)
 
        /* all states are processed in sequence */
        if (appctx->st0 == STAT_HTTP_HEAD) {
-               if (stats_send_htx_headers(si, res_htx)) {
+               if (stats_send_http_headers(si, res_htx)) {
                        if (s->txn->meth == HTTP_METH_HEAD)
                                appctx->st0 = STAT_HTTP_DONE;
                        else
@@ -3355,7 +3247,7 @@ static void htx_stats_io_handler(struct appctx *appctx)
        }
 
        if (appctx->st0 == STAT_HTTP_LAST) {
-               if (stats_send_htx_redirect(si, res_htx))
+               if (stats_send_http_redirect(si, res_htx))
                        appctx->st0 = STAT_HTTP_DONE;
        }
 
@@ -3396,145 +3288,6 @@ static void htx_stats_io_handler(struct appctx *appctx)
                si_stop_get(si);
 }
 
-
-/* This I/O handler runs as an applet embedded in a stream interface. It is
- * used to send HTTP stats over a TCP socket. The mechanism is very simple.
- * appctx->st0 contains the operation in progress (dump, done). The handler
- * automatically unregisters itself once transfer is complete.
- */
-static void http_stats_io_handler(struct appctx *appctx)
-{
-       struct stream_interface *si = appctx->owner;
-       struct stream *s = si_strm(si);
-       struct channel *req = si_oc(si);
-       struct channel *res = si_ic(si);
-
-       if (IS_HTX_STRM(s))
-               return htx_stats_io_handler(appctx);
-
-       if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
-               goto out;
-
-       /* Check if the input buffer is available. */
-       if (res->buf.size == 0) {
-               /* already subscribed, we'll be called later once the buffer is
-                * available.
-                */
-               goto out;
-       }
-
-       /* check that the output is not closed */
-       if (res->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_SHUTR))
-               appctx->st0 = STAT_HTTP_END;
-
-       /* all states are processed in sequence */
-       if (appctx->st0 == STAT_HTTP_HEAD) {
-               if (stats_send_http_headers(si)) {
-                       if (s->txn->meth == HTTP_METH_HEAD)
-                               appctx->st0 = STAT_HTTP_DONE;
-                       else
-                               appctx->st0 = STAT_HTTP_DUMP;
-               }
-       }
-
-       if (appctx->st0 == STAT_HTTP_DUMP) {
-               unsigned int prev_len = ci_data(si_ic(si));
-               unsigned int data_len;
-               unsigned int last_len;
-               unsigned int last_fwd = 0;
-
-               if (appctx->ctx.stats.flags & STAT_CHUNKED) {
-                       /* One difficulty we're facing is that we must prevent
-                        * the input data from being automatically forwarded to
-                        * the output area. For this, we temporarily disable
-                        * forwarding on the channel.
-                        */
-                       last_fwd = si_ic(si)->to_forward;
-                       si_ic(si)->to_forward = 0;
-                       chunk_printf(&trash, "\r\n000000\r\n");
-                       if (ci_putchk(si_ic(si), &trash) == -1) {
-                               si_rx_room_blk(si);
-                               si_ic(si)->to_forward = last_fwd;
-                               goto out;
-                       }
-               }
-
-               data_len = ci_data(si_ic(si));
-               if (stats_dump_stat_to_buffer(si, NULL, s->be->uri_auth))
-                       appctx->st0 = STAT_HTTP_DONE;
-
-               last_len = ci_data(si_ic(si));
-
-               /* Now we must either adjust or remove the chunk size. This is
-                * not easy because the chunk size might wrap at the end of the
-                * buffer, so we pretend we have nothing in the buffer, we write
-                * the size, then restore the buffer's contents. Note that we can
-                * only do that because no forwarding is scheduled on the stats
-                * applet.
-                */
-               if (appctx->ctx.stats.flags & STAT_CHUNKED) {
-                       si_ic(si)->total -= (last_len - prev_len);
-                       b_sub(si_ib(si), (last_len - prev_len));
-
-                       if (last_len != data_len) {
-                               chunk_printf(&trash, "\r\n%06x\r\n", (last_len - data_len));
-                               if (ci_putchk(si_ic(si), &trash) == -1)
-                                       si_rx_room_blk(si);
-
-                               si_ic(si)->total += (last_len - data_len);
-                               b_add(si_ib(si), last_len - data_len);
-                       }
-                       /* now re-enable forwarding */
-                       channel_forward(si_ic(si), last_fwd);
-               }
-       }
-
-       if (appctx->st0 == STAT_HTTP_POST) {
-               if (stats_process_http_post(si))
-                       appctx->st0 = STAT_HTTP_LAST;
-               else if (si_oc(si)->flags & CF_SHUTR)
-                       appctx->st0 = STAT_HTTP_DONE;
-       }
-
-       if (appctx->st0 == STAT_HTTP_LAST) {
-               if (stats_send_http_redirect(si))
-                       appctx->st0 = STAT_HTTP_DONE;
-       }
-
-       if (appctx->st0 == STAT_HTTP_DONE) {
-               if (appctx->ctx.stats.flags & STAT_CHUNKED) {
-                       chunk_printf(&trash, "\r\n0\r\n\r\n");
-                       if (ci_putchk(si_ic(si), &trash) == -1) {
-                               si_rx_room_blk(si);
-                               goto out;
-                       }
-               }
-               appctx->st0 = STAT_HTTP_END;
-       }
-
-       if (appctx->st0 == STAT_HTTP_END) {
-               if (!(res->flags & CF_SHUTR)) {
-                       res->flags |= CF_READ_NULL;
-                       si_shutr(si);
-               }
-
-               /* eat the whole request */
-               if (co_data(req))
-                       co_skip(si_oc(si), co_data(si_oc(si)));
-       }
-
- out:
-       /* we have left the request in the buffer for the case where we
-        * process a POST, and this automatically re-enables activity on
-        * read. It's better to indicate that we want to stop reading when
-        * we're sending, so that we know there's at most one direction
-        * deciding to wake the applet up. It saves it from looping when
-        * emitting large blocks into small TCP windows.
-        */
-       if (!channel_is_empty(res))
-               si_stop_get(si);
-}
-
 /* Dump all fields from <info> into <out> using the "show info" format (name: value) */
 static int stats_dump_info_fields(struct buffer *out,
                                  const struct field *info)