MEDIUM: http: add a new option http-buffer-request
It is sometimes desirable to wait for the body of an HTTP request before
taking a decision. This is what is being done by "balance url_param" for
example. The first use case is to buffer requests from slow clients before
connecting to the server. Another use case consists in taking the routing
decision based on the request body's contents. This option placed in a
frontend or backend forces the HTTP processing to wait until either the whole
body is received, or the request buffer is full, or the first chunk is
complete in case of chunked encoding. It can have undesired side effects with
some applications abusing HTTP by expecting unbufferred transmissions between
the frontend and the backend, so this should definitely not be used by
default.
Note that it would not work for the response because we don't reset the
message state before starting to forward. For the response we need to
1) reset the message state to MSG_100_SENT or BODY , and 2) to reset
body_len in case of chunked encoding to avoid counting it twice.
diff --git a/src/proto_http.c b/src/proto_http.c
index dc59981..6bd89bc 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3133,6 +3133,11 @@
((sess->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE)))
http_adjust_conn_mode(s, txn, msg);
+ /* we may have to wait for the request's body */
+ if ((s->be->options & PR_O_WREQ_BODY) &&
+ (msg->body_len || (msg->flags & HTTP_MSGF_TE_CHNK)))
+ req->analysers |= AN_REQ_HTTP_BODY;
+
/* end of job, return OK */
req->analysers &= ~an_bit;
req->analyse_exp = TICK_ETERNITY;
@@ -3288,7 +3293,7 @@
}
/* Was the status page requested with a POST ? */
- if (unlikely(txn->meth == HTTP_METH_POST && txn->req.body_len > 0)) {
+ if (unlikely(txn->meth == HTTP_METH_POST && txn->req.body_len > 0 && msg->msg_state < HTTP_MSG_BODY)) {
if (appctx->ctx.stats.flags & STAT_ADMIN) {
/* we'll need the request body, possibly after sending 100-continue */
req->analysers |= AN_REQ_HTTP_BODY;