6f1b2c7eb6c8f8706e55bd3ba42ab84191f8c7f9
[feed/packages.git] / net / haproxy / patches / 0016-BUG-MEDIUM-http-adjust-close-mode-when-switching-to-.patch
1 From 2e47a3ab11188239abadb6bba7bd901d764aa4fb Mon Sep 17 00:00:00 2001
2 From: Willy Tarreau <w@1wt.eu>
3 Date: Tue, 30 Sep 2014 18:44:22 +0200
4 Subject: [PATCH 16/20] BUG/MEDIUM: http: adjust close mode when switching to
5 backend
6
7 Commit 179085c ("MEDIUM: http: move Connection header processing earlier")
8 introduced a regression : the backend's HTTP mode is not considered anymore
9 when setting the session's HTTP mode, because wait_for_request() is only
10 called once, when the frontend receives the request (or when the frontend
11 is in TCP mode, when the backend receives the request).
12
13 The net effect is that in some situations when the frontend and the backend
14 do not work in the same mode (eg: keep-alive vs close), the backend's mode
15 is ignored.
16
17 This patch moves all that processing to a dedicated function, which is
18 called from the original place, as well as from session_set_backend()
19 when switching from an HTTP frontend to an HTTP backend in different
20 modes.
21
22 This fix must be backported to 1.5.
23 (cherry picked from commit 4e21ff9244aefa56bcf0793a9e07edba2c3c1960)
24 ---
25 include/proto/proto_http.h | 1 +
26 src/proto_http.c | 107 +++++++++++++++++++++++----------------------
27 src/proxy.c | 8 ++++
28 3 files changed, 64 insertions(+), 52 deletions(-)
29
30 diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
31 index e898ca8..8014310 100644
32 --- a/include/proto/proto_http.h
33 +++ b/include/proto/proto_http.h
34 @@ -112,6 +112,7 @@ unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hle
35 void http_init_txn(struct session *s);
36 void http_end_txn(struct session *s);
37 void http_reset_txn(struct session *s);
38 +void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg);
39
40 struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
41 struct http_res_rule *parse_http_res_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
42 diff --git a/src/proto_http.c b/src/proto_http.c
43 index 7e35c8b..20e7088 100644
44 --- a/src/proto_http.c
45 +++ b/src/proto_http.c
46 @@ -2393,6 +2393,59 @@ fail:
47 return 0;
48 }
49
50 +void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg)
51 +{
52 + int tmp = TX_CON_WANT_KAL;
53 +
54 + if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
55 + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
56 + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
57 + tmp = TX_CON_WANT_TUN;
58 +
59 + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
60 + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
61 + tmp = TX_CON_WANT_TUN;
62 + }
63 +
64 + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
65 + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
66 + /* option httpclose + server_close => forceclose */
67 + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
68 + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
69 + tmp = TX_CON_WANT_CLO;
70 + else
71 + tmp = TX_CON_WANT_SCL;
72 + }
73 +
74 + if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
75 + (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
76 + tmp = TX_CON_WANT_CLO;
77 +
78 + if ((txn->flags & TX_CON_WANT_MSK) < tmp)
79 + txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
80 +
81 + if (!(txn->flags & TX_HDR_CONN_PRS) &&
82 + (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
83 + /* parse the Connection header and possibly clean it */
84 + int to_del = 0;
85 + if ((msg->flags & HTTP_MSGF_VER_11) ||
86 + ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
87 + !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
88 + to_del |= 2; /* remove "keep-alive" */
89 + if (!(msg->flags & HTTP_MSGF_VER_11))
90 + to_del |= 1; /* remove "close" */
91 + http_parse_connection_header(txn, msg, to_del);
92 + }
93 +
94 + /* check if client or config asks for explicit close in KAL/SCL */
95 + if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
96 + (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
97 + ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */
98 + (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
99 + !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */
100 + s->fe->state == PR_STSTOPPED)) /* frontend is stopping */
101 + txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
102 +}
103
104 /* This stream analyser waits for a complete HTTP request. It returns 1 if the
105 * processing can continue on next analysers, or zero if it either needs more
106 @@ -2929,58 +2982,8 @@ int http_wait_for_request(struct session *s, struct channel *req, int an_bit)
107 * time.
108 */
109 if (!(txn->flags & TX_HDR_CONN_PRS) ||
110 - ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) {
111 - int tmp = TX_CON_WANT_KAL;
112 -
113 - if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
114 - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
115 - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
116 - tmp = TX_CON_WANT_TUN;
117 -
118 - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
119 - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
120 - tmp = TX_CON_WANT_TUN;
121 - }
122 -
123 - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
124 - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
125 - /* option httpclose + server_close => forceclose */
126 - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
127 - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
128 - tmp = TX_CON_WANT_CLO;
129 - else
130 - tmp = TX_CON_WANT_SCL;
131 - }
132 -
133 - if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
134 - (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
135 - tmp = TX_CON_WANT_CLO;
136 -
137 - if ((txn->flags & TX_CON_WANT_MSK) < tmp)
138 - txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
139 -
140 - if (!(txn->flags & TX_HDR_CONN_PRS) &&
141 - (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
142 - /* parse the Connection header and possibly clean it */
143 - int to_del = 0;
144 - if ((msg->flags & HTTP_MSGF_VER_11) ||
145 - ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
146 - !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
147 - to_del |= 2; /* remove "keep-alive" */
148 - if (!(msg->flags & HTTP_MSGF_VER_11))
149 - to_del |= 1; /* remove "close" */
150 - http_parse_connection_header(txn, msg, to_del);
151 - }
152 -
153 - /* check if client or config asks for explicit close in KAL/SCL */
154 - if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
155 - (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
156 - ((txn->flags & TX_HDR_CONN_CLO) || /* "connection: close" */
157 - (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
158 - !(msg->flags & HTTP_MSGF_XFER_LEN) || /* no length known => close */
159 - s->fe->state == PR_STSTOPPED)) /* frontend is stopping */
160 - txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
161 - }
162 + ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE)))
163 + http_adjust_conn_mode(s, txn, msg);
164
165 /* end of job, return OK */
166 req->analysers &= ~an_bit;
167 diff --git a/src/proxy.c b/src/proxy.c
168 index 02103ee..405c4c4 100644
169 --- a/src/proxy.c
170 +++ b/src/proxy.c
171 @@ -955,6 +955,14 @@ int session_set_backend(struct session *s, struct proxy *be)
172 http_init_txn(s);
173 }
174
175 + /* If we chain to an HTTP backend running a different HTTP mode, we
176 + * have to re-adjust the desired keep-alive/close mode to accommodate
177 + * both the frontend's and the backend's modes.
178 + */
179 + if (s->fe->mode == PR_MODE_HTTP && be->mode == PR_MODE_HTTP &&
180 + ((s->fe->options & PR_O_HTTP_MODE) != (be->options & PR_O_HTTP_MODE)))
181 + http_adjust_conn_mode(s, &s->txn, &s->txn.req);
182 +
183 /* If an LB algorithm needs to access some pre-parsed body contents,
184 * we must not start to forward anything until the connection is
185 * confirmed otherwise we'll lose the pointer to these data and
186 --
187 2.0.4
188