- From: Richard Bradbury <richard.bradbury@rd.bbc.co.uk>
- Date: Wed, 29 Oct 2025 12:51:22 +0000
- To: HTTP Working Group <ietf-http-wg@w3.org>
- Message-ID: <48b09584-17ca-46ea-8522-27372e2f777d@rd.bbc.co.uk>
Thanks for the suggestion to use a multipart partial content response instead of chunked transfer. Reading section 15.3.7.2 of RFC 9110 <https://www.rfc-editor.org/rfc/rfc9110.html#section-15.3.7.2>, the requirement for the HTTP client to request at least two byte ranges to elicit a multipart/byterange response is certainly satisfied by requesting Range: bytes=0-,0-. Requesting the whole representation twice doesn't seem /too/ much of a hack. Likewise, I don't have any problem with a multipart/byterange response. Overall, it seems quite a neat solution. One wrinkle is working out how the responding HTTP server (the gateway in this Use Case) populates Content-Length at the start of its response. It's hard for it to predict how many "parts" the received object will need to be split into. One implementation strategy would be to decide up front on a fixed set of blocks and to stick with that target block pattern regardless of how/when multicast packets arrive at the gateway. I'm not sure if that lack of flexibility would be a problem in practice or not. Thanks also for pointing me at your Internet Draft covering push-based Use Cases. On 27/10/2025 02:52, Austin Wright wrote: > Since the chunked encoding extension points have no equivalent in > other HTTP versions, they are going to be highly disfavored. Even if > they were, you would also need a way for clients to signal that they > would read the extension, instead of ignoring it. However, I think > there’s a better mechanism that’s well supported and will get you most > of the way there. > > Did you consider partial content responses > <https://www.rfc-editor.org/rfc/rfc9110.html#name-206-partial-content> for > your needs? While parts are typically provided in order, they can be > delivered out-of-order, and you can deliver the entire resource this way. > > To upload documents, requests could use the PATCH method. Since > “multipart/byteranges” is often disfavored, I have an Internet-Draft > over in the HTTP APIs working group called “Byte Range PATCH” that > defines alternative formats; I would appreciate your review: > https://datatracker.ietf.org/doc/draft-ietf-httpapi-patch-byterange/ > > Responses are be carried in a 206 (Partial Content) response, to a > client that indicates it supports these responses. To indicate support > for multipart responses (where each part lists its own Content-Range > field, instead of in the response headers), you must make a Range > request with multiple ranges; this suggests you can make a Range > request listing the whole resource twice, and the server should > interpret this as support for multipart partial content responses for > the whole document: > > > Range 0-, 0- > > If this sounds like too much of a hack, the alternative would be to > introduce a new field that indicates which multipart response formats > are permissible: > > > Accept-Multipart: message/byterange, multipart/byteranges, > application/byteranges > > In particular, application/byteranges is a proposed binary format that > would be defined by Byte Range PATCH. If you would find this > useful, please let us know over there. > > >> On Oct 20, 2025, at 08:40, Richard Bradbury wrote: >> >> I am seeking expert opinion on a candidate solution to a Real World >> Use Case with which I was recently presented. >> >> TL;DR: >> >> * Would it be legitimate to extend HTTP/1.1 chunked transfer coding >> to support delivery of chunks out of order? >> * Is such an extension a useful thing to standardise? >> >> >> Use Case description >> >> The Use Case involves transmitting Binary Large Objects (BLOBs) in a >> multicast FLUTE v1 <https://www.rfc-editor.org/rfc/rfc3926.html> >> session operating in carousel mode (i.e., FLUTE transmission objects >> in the session are sent repeatedly, possibly interleaved). The >> receiver is a gateway device offering an HTTP endpoint to downstream >> clients that want to acquire one or more transmission objects of >> interest to them. >> >> Steps: >> >> 1. A client requests an HTTP resource from the gateway, citing it's URL. >> 2. The gateway joins the appropriate multicast group (based on some >> look-up mechanism not of concern here) and starts receiving FLUTE >> transmission objects, including the File Delivery Table >> <https://www.rfc-editor.org/rfc/rfc3926.html#section-3.2> >> transmission object. >> 3. The gateway looks up the URL requested by the client in the File >> Delivery Table of the FLUTE session and this yields the >> Transmission Object Identifier that it needs to acquire. >> 4. The gateway starts receiving FLUTE packets (well, actually >> ALC/LCT packets) for the identified transmission object and sends >> their payloads to the requesting client in the HTTP response body. >> >> So far, so vanilla. >> >> The twist is that the gateway has a low memory footprint, much >> smaller than the size of the BLOBs being transmitted in the FLUTE >> session. Hence, it cannot operate in a store-and-forward mode, and >> needs instead to deliver incoming data from the FLUTE session to its >> client in an efficient, pipelined fashion, minimising the need for >> buffering and anything beyond simple reassembly of received data >> blocks. Moreover, the client request to the gateway (step 1 above) >> arrives at a random time during the FLUTE session, in the worst case >> towards the end of a rotation of the carousel. In addition, the >> gateway may occasionally drop received FLUTE packets. >> >> >> Candidate solutions >> >> My first instinct is always to try and reuse existing building blocks >> wherever possible, rather than inventing something new. >> >> >> HTTP/1.1 >> >> The *chunked transfer coding* feature that all HTTP/1.1 clients and >> servers are required to implement seems a good fit, except for one >> small detail: it assumes in-order delivery of chunks. Each chunk >> follows on from the last and is appended by the HTTP recipient to the >> previously received chunk (if any). >> >> My idea is to include with every chunk a name–value pair (e.g. >> "offset=...") that additionally signals the byte position of this >> chunk in the overall resource representation. I reckon this could be >> achieved in the chunk delimiter using the *chunk-ext* production >> specified in section 7.1 of RFC 9112 >> <https://www.rfc-editor.org/rfc/rfc9112#name-chunked-transfer-coding>. >> For example: >> >> 1fb;offset="40d4" >> >> With this additional signalling, the chunks could be sent on by the >> gateway to the client in whichever order they are received from the >> multicast FLUTE session, even if the gateway joins the multicast >> group partway through a carousel rotation. And the client could, for >> example, write received chunks to a sparse file using lseek() as they >> arrive in the HTTP response body. Happy days. >> >> Once the entire transmission object has been received by the gateway >> and forwarded to the requesting client, the HTTP response body is >> terminated with the standard zero-length chunk. (More than one full >> rotation of the FLUTE carousel may be required to satisfy this >> termination condition in the presence of packet loss.) >> >> In the absence of the proposed "offset=..." extension, a received >> chunk is assumed to belong immediately after the one previously >> received, as now, so the signalling is backwards-compatible with RFC >> 9112. >> >> >> HTTP/2 >> >> /(Not an immediate requirement, but I include an analysis for >> completeness.)/ >> >> This protocol version effectively uses chunked transfer for all >> message bodies, thanks to its binary framing. The HTTP/2 DATA frame >> includes length but not position. Being based on TCP, HTTP/2 client >> implementations are likely not expecting to receive DATA frames out >> of order. Since chunked transfer coding is explicitly prohibited by >> section 8.1 of RFC 9113 >> <https://www.rfc-editor.org/rfc/rfc9113.html#name-http-message-framing> >> it seems very difficult to achieve our of order delivery with this >> version of HTTP. >> >> >> HTTP/3 >> >> /(Not an immediate requirement, but I include an analysis for >> completeness.)/ >> >> Again, this protocol version natively uses chunked transfers. Similar >> to HTTP/2, the HTTP/3 DATA frame header signals the frame length. The >> position of this in the underlying QUIC stream is explicitly encoded >> in the /Offset/ field of the QUIC STREAM frame header, so there is >> potential to get cute with HTTP/3 DATA frame delivery order, provided >> the size of the HTTP/3 DATA frame headers (which can contain >> variable-length integers) is properly accounted for and no other >> frames are sent on that QUIC stream. I can't decide if that's elegant >> or evil. Maybe both at the same time. >> >> Although QUIC streams are intended to offer an in-order bytestream >> abstraction to applications, being a UDP-based protocol, QUIC >> endpoints need to be robust to receiving datagrams out of order, to >> some extent. I note in particular the following in section 2.2 of RFC >> 9000 >> <https://www.rfc-editor.org/rfc/rfc9000.html#name-sending-and-receiving-data>: >> >> "Endpoints MUST be able to deliver stream data to an application >> as an ordered byte stream. Delivering an ordered byte stream >> requires that an endpoint buffer any data that is received out of >> order, up to the advertised flow control limit. >> >> QUIC makes no specific allowances for delivery of stream data out >> of order. However, implementations MAY choose to offer the >> ability to deliver data out of order to a receiving application." >> >> Hence, sending QUIC STREAM frames with unordered /Offset/ values >> seems to be a potentially viable solution to satisfy the Use Case >> that is sort of in keeping with the spirit of RFC 9000. >> >> Whether HTTP/3 client implementations are robust to receiving DATA >> frames out of order is another matter, of course, but that would be a >> requirement for supporting this Use Case. (Unlike the >> resource-constrained gateway, the end client in this Use Case is less >> constrained.) >>
Received on Wednesday, 29 October 2025 12:51:29 UTC