From: Amaury Denoyelle Date: Fri, 4 Aug 2023 14:10:18 +0000 (+0200) Subject: MINOR: h3: abort request if not completed before full response X-Git-Tag: v2.9-dev3~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=559482c11e605b0f19714e47368a9a5ccbdca3cb;p=thirdparty%2Fhaproxy.git MINOR: h3: abort request if not completed before full response A HTTP server may provide a complete response even prior receiving the full request. In this case, RFC 9114 allows the server to abort read with a STOP_SENDING with error code H3_NO_ERROR. This scenario was notably reproduced with haproxy and an inactive server. If the client send a POST request, haproxy may provide a full HTTP 503 response before the end of the full request. --- diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index 8b861f7005..872c5eafe5 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -15,6 +15,8 @@ void qcc_set_error(struct qcc *qcc, int err, int app); struct qcs *qcc_init_stream_local(struct qcc *qcc, int bidi); struct stconn *qcs_attach_sc(struct qcs *qcs, struct buffer *buf, char fin); +int qcs_is_close_local(struct qcs *qcs); +int qcs_is_close_remote(struct qcs *qcs); struct buffer *qcs_get_buf(struct qcs *qcs, struct buffer *bptr); int qcs_subscribe(struct qcs *qcs, int event_type, struct wait_event *es); diff --git a/src/h3.c b/src/h3.c index 94b50ba904..b10851baa1 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1673,6 +1673,31 @@ static size_t h3_snd_buf(struct qcs *qcs, struct htx *htx, size_t count) } } + /* RFC 9114 4.1. HTTP Message Framing + * + * A server can send a complete response prior to the client sending an + * entire request if the response does not depend on any portion of the + * request that has not been sent and received. When the server does not + * need to receive the remainder of the request, it MAY abort reading + * the request stream, send a complete response, and cleanly close the + * sending part of the stream. The error code H3_NO_ERROR SHOULD be used + * when requesting that the client stop sending on the request stream. + * Clients MUST NOT discard complete responses as a result of having + * their request terminated abruptly, though clients can always discard + * responses at their discretion for other reasons. If the server sends + * a partial or complete response but does not abort reading the + * request, clients SHOULD continue sending the content of the request + * and close the stream normally. + */ + if (unlikely((htx->flags & HTX_FL_EOM) && htx_is_empty(htx)) && + !qcs_is_close_remote(qcs)) { + /* Generate a STOP_SENDING if full response transferred before + * receiving the full request. + */ + qcs->err = H3_NO_ERROR; + qcc_abort_stream_read(qcs); + } + out: return total; } diff --git a/src/mux_quic.c b/src/mux_quic.c index 2c400b446f..698bacf082 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -403,12 +403,12 @@ static void qcs_close_remote(struct qcs *qcs) } } -static int qcs_is_close_local(struct qcs *qcs) +int qcs_is_close_local(struct qcs *qcs) { return qcs->st == QC_SS_HLOC || qcs->st == QC_SS_CLO; } -static int qcs_is_close_remote(struct qcs *qcs) +int qcs_is_close_remote(struct qcs *qcs) { return qcs->st == QC_SS_HREM || qcs->st == QC_SS_CLO; }