]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: abort request if not completed before full response
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 4 Aug 2023 14:10:18 +0000 (16:10 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 4 Aug 2023 14:17:16 +0000 (16:17 +0200)
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.

include/haproxy/mux_quic.h
src/h3.c
src/mux_quic.c

index 8b861f7005e7ce8097a5ad4badd1d2283b217301..872c5eafe523d0f473378ded1bac6e217b27d82f 100644 (file)
@@ -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);
index 94b50ba90472ee4d92f96efdd169424511855573..b10851baa1b445cef5c1a50de3a210314f099935 100644 (file)
--- 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;
 }
index 2c400b446f18fda814cd02e9f5c3a04b66db7ac6..698bacf082b2c78cdbef9dbcabfde80fa11e0acb 100644 (file)
@@ -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;
 }