BUG/MEDIUM: http/session: disable client-side expiration only after body
For a very long time, back in the v1.3 days, we used to rely on a trick
to avoid expiring the client side while transferring a payload to the
server. The problem was that if a client was able to quickly fill the
buffers, and these buffers took some time to reach the server, the
client should not expire while not sending anything.
In order to cover this situation, the client-side timeout was disabled
once the connection to the server was OK, since it implied that we would
at least expire on the server if required.
But there is a drawback to this : if a client stops uploading data before
the end, its timeout is not enforced and we only expire on the server's
timeout, so the logs report a 504.
Since 1.4, we have message body analysers which ensure that we know whether
all the expected data was received or not (HTTP_MSG_DATA or HTTP_MSG_DONE).
So we can fix this problem by disabling the client-side or server-side
timeout at the end of the transfer for the respective side instead of
having it unconditionally in session.c during all the transfer.
With this, the logs now report the correct side for the timeout. Note that
this patch is not enough, because another issue remains : the HTTP body
forwarders do not abort upon timeout, they simply rely on the generic
handling from session.c. So for now, the session is still aborted when
reaching the server timeout, but the culprit is properly reported. A
subsequent patch will address this specific point.
This bug was tagged MEDIUM because of the changes performed. The issue
it fixes is minor however. After some cooling down, it may be backported
to 1.4.
It was reported by and discussed with Rachel Chavez and Patrick Hemmer
on the mailing list.
diff --git a/src/proto_http.c b/src/proto_http.c
index 24c7cf8..e473228 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5341,6 +5341,11 @@
channel_auto_read(req);
}
+ /* if we received everything, we don't want to expire anymore */
+ if (msg->msg_state == HTTP_MSG_DONE) {
+ req->flags |= CF_READ_NOEXP;
+ req->rex = TICK_ETERNITY;
+ }
return 0;
}
}
@@ -6529,6 +6534,12 @@
}
return 1;
}
+
+ /* if we received everything, we don't want to expire anymore */
+ if (msg->msg_state == HTTP_MSG_DONE) {
+ res->flags |= CF_READ_NOEXP;
+ res->rex = TICK_ETERNITY;
+ }
return 0;
}
}