|
@@ -0,0 +1,188 @@
|
|
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
|
+
|