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.
This commit is contained in:
Willy Tarreau 2015-12-07 17:04:59 +01:00
parent baf9794b4d
commit 858b103631

View File

@ -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