BUG/MINOR: mux-h2: do not send REFUSED_STREAM on aborted uploads

If the server decides to close early, we don't want to send a
REFUSED_STREAM error but a CANCEL, so that the client doesn't want
to retry. The test in h2_do_shutw() was wrong for this as it would
handle the HLOC case like the case where nothing had been sent for
this stream, which is wrong. Now h2_do_shutw() does nothing in this
case and lets h2_do_shutr() decide.

Note that this partially undoes f983d00a1 ("BUG/MINOR: mux-h2: make
the do_shut{r,w} functions more robust against retries").

This must be backported to 2.0. The patch above was not backported to
1.9 for being too risky there, but if it eventually gets to it, this
one will be needed as well.
This commit is contained in:
Willy Tarreau 2019-08-06 10:30:58 +02:00
parent 082c45769b
commit cfba9d6eaa

View File

@ -3267,6 +3267,14 @@ static void h2_do_shutr(struct h2s *h2s)
*/
h2s_error(h2s, H2_ERR_REFUSED_STREAM);
}
else {
/* a final response was already provided, we don't want this
* stream anymore. This may happen when the server responds
* before the end of an upload and closes quickly (redirect,
* deny, ...)
*/
h2s_error(h2s, H2_ERR_CANCEL);
}
if (!(h2s->flags & H2_SF_RST_SENT) &&
h2s_send_rst_stream(h2c, h2s) <= 0)
@ -3300,11 +3308,10 @@ static void h2_do_shutw(struct h2s *h2s)
struct h2c *h2c = h2s->h2c;
struct wait_event *sw = &h2s->wait_event;
if (h2s->st == H2_SS_CLOSED)
if (h2s->st == H2_SS_HLOC || h2s->st == H2_SS_CLOSED)
goto done;
if (h2s->st != H2_SS_HLOC && h2s->st != H2_SS_ERROR &&
(h2s->flags & H2_SF_HEADERS_SENT)) {
if (h2s->st != H2_SS_ERROR && (h2s->flags & H2_SF_HEADERS_SENT)) {
/* we can cleanly close using an empty data frame only after headers */
if (!(h2s->flags & (H2_SF_ES_SENT|H2_SF_RST_SENT)) &&