]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] stats: add support for several packets in stats admin
authorCyril Bonté <cyril.bonte@free.fr>
Thu, 10 Feb 2011 21:54:44 +0000 (22:54 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 12 Feb 2011 12:10:18 +0000 (13:10 +0100)
Some browsers send POST requests in several packets, which was not supported
by the "stats admin" function.

This patch allows to wait for more data when they are not fully received
(we are still limited to a certain size defined by the buffer size minus its
reserved space).
It also adds support for the "Expect: 100-Continue" header.

doc/configuration.txt
src/proto_http.c

index bb25448ea1b3a97900439b2b7783e9014f0a9a96..c768fc72cc0ba909816d77e52df6d2e98a987a26 100644 (file)
@@ -4856,13 +4856,10 @@ stats admin { if | unless } <cond>
          unless you know what you do : memory is not shared between the
          processes, which can result in random behaviours.
 
-  Currently, there are 2 known limitations :
-
-    - The POST data are limited to one packet, which means that if the list of
-      servers is too long, the request won't be processed. It is recommended
-      to alter few servers at a time.
-
-    - Expect: 100-continue is not supported.
+  Currently, the POST request is limited to the buffer size minus the reserved
+  buffer space, which means that if the list of servers is too long, the
+  request won't be processed. It is recommended to alter few servers at a
+  time.
 
   Example :
     # statistics admin level only for localhost
index dbd6a2e81498182520d3aa3ef91dffcb9446529d..3a404e67cc4fe10ed8cc16ddc45f7904f780f5d6 100644 (file)
@@ -2855,8 +2855,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
 
 /* We reached the stats page through a POST request.
  * Parse the posted data and enable/disable servers if necessary.
- * Returns 0 if request was parsed.
- * Returns 1 if there was a problem parsing the posted data.
+ * Returns 1 if request was parsed or zero if it needs more data.
  */
 int http_process_req_stat_post(struct session *s, struct buffer *req)
 {
@@ -2874,15 +2873,15 @@ int http_process_req_stat_post(struct session *s, struct buffer *req)
 
        cur_param = next_param = end_params;
 
-       if (end_params >= req->data + req->size) {
+       if (end_params >= req->data + req->size - global.tune.maxrewrite) {
                /* Prevent buffer overflow */
                s->data_ctx.stats.st_code = STAT_STATUS_EXCD;
                return 1;
        }
        else if (end_params > req->data + req->l) {
-               /* This condition also rejects a request with Expect: 100-continue */
-               s->data_ctx.stats.st_code = STAT_STATUS_EXCD;
-               return 1;
+               /* we need more data */
+               s->data_ctx.stats.st_code = STAT_STATUS_NONE;
+               return 0;
        }
 
        *end_params = '\0';
@@ -2955,7 +2954,7 @@ int http_process_req_stat_post(struct session *s, struct buffer *req)
                        next_param = cur_param;
                }
        }
-       return 0;
+       return 1;
 }
 
 /* This stream analyser runs all HTTP request processing which is common to
@@ -3195,7 +3194,28 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
                /* Was the status page requested with a POST ? */
                if (txn->meth == HTTP_METH_POST) {
                        if (s->data_ctx.stats.flags & STAT_ADMIN) {
-                               http_process_req_stat_post(s, req);
+                               if (msg->msg_state < HTTP_MSG_100_SENT) {
+                                       /* If we have HTTP/1.1 and Expect: 100-continue, then we must
+                                        * send an HTTP/1.1 100 Continue intermediate response.
+                                        */
+                                       if (txn->flags & TX_REQ_VER_11) {
+                                               struct hdr_ctx ctx;
+                                               ctx.idx = 0;
+                                               /* Expect is allowed in 1.1, look for it */
+                                               if (http_find_header2("Expect", 6, msg->sol, &txn->hdr_idx, &ctx) &&
+                                                   unlikely(ctx.vlen == 12 && strncasecmp(ctx.line+ctx.val, "100-continue", 12) == 0)) {
+                                                       buffer_write(s->rep, http_100_chunk.str, http_100_chunk.len);
+                                               }
+                                       }
+                                       msg->msg_state = HTTP_MSG_100_SENT;
+                                       s->logs.tv_request = now;  /* update the request timer to reflect full request */
+                               }
+                               if (!http_process_req_stat_post(s, req)) {
+                                       /* we need more data */
+                                       req->analysers |= an_bit;
+                                       buffer_dont_connect(req);
+                                       return 0;
+                               }
                        } else {
                                s->data_ctx.stats.st_code = STAT_STATUS_DENY;
                        }