forked from pool/haproxy
9713333582
1 OBS-URL: https://build.opensuse.org/request/show/254377 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/haproxy?expand=0&rev=14
189 lines
7.9 KiB
Diff
189 lines
7.9 KiB
Diff
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
|
|
--
|
|
1.8.4.5
|
|
|