|
|
- From 2e47a3ab11188239abadb6bba7bd901d764aa4fb Mon Sep 17 00:00:00 2001
- From: Willy Tarreau <w@1wt.eu>
- Date: Tue, 30 Sep 2014 18:44:22 +0200
- Subject: [PATCH 16/20] BUG/MEDIUM: http: adjust close mode when switching to
- backend
-
- Commit 179085c ("MEDIUM: http: move Connection header processing earlier")
- introduced a regression : the backend's HTTP mode is not considered anymore
- when setting the session's HTTP mode, because wait_for_request() is only
- called once, when the frontend receives the request (or when the frontend
- is in TCP mode, when the backend receives the request).
-
- The net effect is that in some situations when the frontend and the backend
- do not work in the same mode (eg: keep-alive vs close), the backend's mode
- is ignored.
-
- This patch moves all that processing to a dedicated function, which is
- called from the original place, as well as from session_set_backend()
- when switching from an HTTP frontend to an HTTP backend in different
- modes.
-
- This fix must be backported to 1.5.
- (cherry picked from commit 4e21ff9244aefa56bcf0793a9e07edba2c3c1960)
- ---
- include/proto/proto_http.h | 1 +
- src/proto_http.c | 107 +++++++++++++++++++++++----------------------
- src/proxy.c | 8 ++++
- 3 files changed, 64 insertions(+), 52 deletions(-)
-
- diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
- index e898ca8..8014310 100644
- --- a/include/proto/proto_http.h
- +++ b/include/proto/proto_http.h
- @@ -112,6 +112,7 @@ unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hle
- void http_init_txn(struct session *s);
- void http_end_txn(struct session *s);
- void http_reset_txn(struct session *s);
- +void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg);
-
- struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
- struct http_res_rule *parse_http_res_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
- diff --git a/src/proto_http.c b/src/proto_http.c
- index 7e35c8b..20e7088 100644
- --- a/src/proto_http.c
- +++ b/src/proto_http.c
- @@ -2393,6 +2393,59 @@ fail:
- return 0;
- }
-
- +void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg)
- +{
- + int tmp = TX_CON_WANT_KAL;
- +
- + if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
- + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
- + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
- + tmp = TX_CON_WANT_TUN;
- +
- + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
- + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
- + tmp = TX_CON_WANT_TUN;
- + }
- +
- + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
- + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
- + /* option httpclose + server_close => forceclose */
- + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
- + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
- + tmp = TX_CON_WANT_CLO;
- + else
- + tmp = TX_CON_WANT_SCL;
- + }
- +
- + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
- + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
- + tmp = TX_CON_WANT_CLO;
- +
- + if ((txn->flags & TX_CON_WANT_MSK) < tmp)
- + txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
- +
- + if (!(txn->flags & TX_HDR_CONN_PRS) &&
- + (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
- + /* parse the Connection header and possibly clean it */
- + int to_del = 0;
- + if ((msg->flags & HTTP_MSGF_VER_11) ||
- + ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
- + !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
- + to_del |= 2; /* remove "keep-alive" */
- + if (!(msg->flags & HTTP_MSGF_VER_11))
- + to_del |= 1; /* remove "close" */
- + http_parse_connection_header(txn, msg, to_del);
- + }
- +
- + /* check if client or config asks for explicit close in KAL/SCL */
- + if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
- + (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
- + ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */
- + (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
- + !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */
- + s->fe->state == PR_STSTOPPED)) /* frontend is stopping */
- + txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
- +}
-
- /* This stream analyser waits for a complete HTTP request. It returns 1 if the
- * processing can continue on next analysers, or zero if it either needs more
- @@ -2929,58 +2982,8 @@ int http_wait_for_request(struct session *s, struct channel *req, int an_bit)
- * time.
- */
- if (!(txn->flags & TX_HDR_CONN_PRS) ||
- - ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) {
- - int tmp = TX_CON_WANT_KAL;
- -
- - if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
- - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
- - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
- - tmp = TX_CON_WANT_TUN;
- -
- - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
- - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
- - tmp = TX_CON_WANT_TUN;
- - }
- -
- - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
- - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
- - /* option httpclose + server_close => forceclose */
- - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
- - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
- - tmp = TX_CON_WANT_CLO;
- - else
- - tmp = TX_CON_WANT_SCL;
- - }
- -
- - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
- - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
- - tmp = TX_CON_WANT_CLO;
- -
- - if ((txn->flags & TX_CON_WANT_MSK) < tmp)
- - txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
- -
- - if (!(txn->flags & TX_HDR_CONN_PRS) &&
- - (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
- - /* parse the Connection header and possibly clean it */
- - int to_del = 0;
- - if ((msg->flags & HTTP_MSGF_VER_11) ||
- - ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
- - !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
- - to_del |= 2; /* remove "keep-alive" */
- - if (!(msg->flags & HTTP_MSGF_VER_11))
- - to_del |= 1; /* remove "close" */
- - http_parse_connection_header(txn, msg, to_del);
- - }
- -
- - /* check if client or config asks for explicit close in KAL/SCL */
- - if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
- - (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
- - ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */
- - (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
- - !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */
- - s->fe->state == PR_STSTOPPED)) /* frontend is stopping */
- - txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
- - }
- + ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE)))
- + http_adjust_conn_mode(s, txn, msg);
-
- /* end of job, return OK */
- req->analysers &= ~an_bit;
- diff --git a/src/proxy.c b/src/proxy.c
- index 02103ee..405c4c4 100644
- --- a/src/proxy.c
- +++ b/src/proxy.c
- @@ -955,6 +955,14 @@ int session_set_backend(struct session *s, struct proxy *be)
- http_init_txn(s);
- }
-
- + /* If we chain to an HTTP backend running a different HTTP mode, we
- + * have to re-adjust the desired keep-alive/close mode to accommodate
- + * both the frontend's and the backend's modes.
- + */
- + if (s->fe->mode == PR_MODE_HTTP && be->mode == PR_MODE_HTTP &&
- + ((s->fe->options & PR_O_HTTP_MODE) != (be->options & PR_O_HTTP_MODE)))
- + http_adjust_conn_mode(s, &s->txn, &s->txn.req);
- +
- /* If an LB algorithm needs to access some pre-parsed body contents,
- * we must not start to forward anything until the connection is
- * confirmed otherwise we'll lose the pointer to these data and
- --
- 2.0.4
-
|