From 858b103631db41c608660210eb37a9e09ee9f086 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 7 Dec 2015 17:04:59 +0100 Subject: [PATCH] BUG/MEDIUM: http: fix http-reuse when frontend and backend differ Krishna Kumar reported that the following configuration doesn't permit HTTP reuse between two clients : frontend private-frontend mode http bind :8001 default_backend private-backend backend private-backend mode http http-reuse always server bck 127.0.0.1:8888 The reason for this is that in http_end_txn_clean_session() we check the stream's backend backend's http-reuse option before deciding whether the backend connection should be moved back to the server's pool or not. But since we're doing this after the call to http_reset_txn(), the backend is reset to match the frontend, which doesn't have the option. However it will work fine in a setup involving a "listen" section. We just need to keep a pointer to the current backend before calling http_reset_txn(). The code does that and replaces the few remaining references to s->be inside the same function so that if any part of code were to be moved later, this trap doesn't happen again. This fix must be backported to 1.6. --- src/proto_http.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index 1d0007172..5fea6c4fc 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -5120,6 +5120,7 @@ void http_end_txn_clean_session(struct stream *s) { int prev_status = s->txn->status; struct proxy *fe = strm_fe(s); + struct proxy *be = s->be; struct connection *srv_conn; struct server *srv; unsigned int prev_flags = s->txn->flags; @@ -5142,7 +5143,7 @@ void http_end_txn_clean_session(struct stream *s) } if (s->flags & SF_BE_ASSIGNED) { - s->be->beconn--; + be->beconn--; if (unlikely(s->srv_conn)) sess_change_server(s, NULL); } @@ -5163,11 +5164,11 @@ void http_end_txn_clean_session(struct stream *s) fe->fe_counters.p.http.comp_rsp++; } if ((s->flags & SF_BE_ASSIGNED) && - (s->be->mode == PR_MODE_HTTP)) { - s->be->be_counters.p.http.rsp[n]++; - s->be->be_counters.p.http.cum_req++; + (be->mode == PR_MODE_HTTP)) { + be->be_counters.p.http.rsp[n]++; + be->be_counters.p.http.cum_req++; if (s->comp_algo && (s->flags & SF_COMP_READY)) - s->be->be_counters.p.http.comp_rsp++; + be->be_counters.p.http.comp_rsp++; } } @@ -5207,7 +5208,7 @@ void http_end_txn_clean_session(struct stream *s) s->flags &= ~SF_CURR_SESS; objt_server(s->target)->cur_sess--; } - if (may_dequeue_tasks(objt_server(s->target), s->be)) + if (may_dequeue_tasks(objt_server(s->target), be)) process_srv_queue(objt_server(s->target)); } @@ -5286,7 +5287,7 @@ void http_end_txn_clean_session(struct stream *s) if (!srv) si_idle_conn(&s->si[1], NULL); else if ((srv_conn->flags & CO_FL_PRIVATE) || - ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR)) + ((be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR)) si_idle_conn(&s->si[1], &srv->priv_conns); else if (prev_flags & TX_NOT_FIRST) /* note: we check the request, not the connection, but