[MINOR] stats: add support for several packets in stats admin

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.
This commit is contained in:
Cyril Bont 2011-02-10 22:54:44 +01:00 committed by Willy Tarreau
parent 5c4784f4b8
commit 23b39d9859
2 changed files with 32 additions and 15 deletions

View File

@ -4856,13 +4856,10 @@ stats admin { if | unless } <cond>
unless you know what you do : memory is not shared between the unless you know what you do : memory is not shared between the
processes, which can result in random behaviours. processes, which can result in random behaviours.
Currently, there are 2 known limitations : 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
- The POST data are limited to one packet, which means that if the list of request won't be processed. It is recommended to alter few servers at a
servers is too long, the request won't be processed. It is recommended time.
to alter few servers at a time.
- Expect: 100-continue is not supported.
Example : Example :
# statistics admin level only for localhost # statistics admin level only for localhost

View 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. /* We reached the stats page through a POST request.
* Parse the posted data and enable/disable servers if necessary. * Parse the posted data and enable/disable servers if necessary.
* Returns 0 if request was parsed. * Returns 1 if request was parsed or zero if it needs more data.
* Returns 1 if there was a problem parsing the posted data.
*/ */
int http_process_req_stat_post(struct session *s, struct buffer *req) 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; 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 */ /* Prevent buffer overflow */
s->data_ctx.stats.st_code = STAT_STATUS_EXCD; s->data_ctx.stats.st_code = STAT_STATUS_EXCD;
return 1; return 1;
} }
else if (end_params > req->data + req->l) { else if (end_params > req->data + req->l) {
/* This condition also rejects a request with Expect: 100-continue */ /* we need more data */
s->data_ctx.stats.st_code = STAT_STATUS_EXCD; s->data_ctx.stats.st_code = STAT_STATUS_NONE;
return 1; return 0;
} }
*end_params = '\0'; *end_params = '\0';
@ -2955,7 +2954,7 @@ int http_process_req_stat_post(struct session *s, struct buffer *req)
next_param = cur_param; next_param = cur_param;
} }
} }
return 0; return 1;
} }
/* This stream analyser runs all HTTP request processing which is common to /* 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 ? */ /* Was the status page requested with a POST ? */
if (txn->meth == HTTP_METH_POST) { if (txn->meth == HTTP_METH_POST) {
if (s->data_ctx.stats.flags & STAT_ADMIN) { 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 { } else {
s->data_ctx.stats.st_code = STAT_STATUS_DENY; s->data_ctx.stats.st_code = STAT_STATUS_DENY;
} }