Rust library to parse and serialize async multipart/x-mixed-replace
streams,
suitable for use with reqwest
, hyper
, and tokio
.
Note multipart/x-mixed-replace
is different than multipart/form-data
; you
might be interested in the
multipart
crate for that.
A multipart stream is a sequence of parts in one HTTP response, each part
having its own headers and body. A stream might last forever, serving parts
that didn't exist at the start of the request. This is a type of "hanging GET"
or Comet request. Each
part might represent the latest state and conceptually replace previous ones,
thus the MIME type multipart/x-mixed-replace
.
It's a simple HTTP/1.1 way of accomplishing what otherwise might require fancier server- and client-side technologies, such as:
Never-ending multipart streams seem popular in the IP camera space:
multipart/x-mixed-replace
stream of events
such as motion detection changes.
(spec)multipart/mixed
stream of events,
as described
here.There's a big limitation, however, which is that browsers have fairly low limits on the number of concurrent connections. In Chrome's case, six per host. For this reason, multipart streams are only suitable in HTTP APIs where the clients are not web browsers.
A multipart response might look like this:
Content-Type: multipart/x-mixed-replace: boundary=B
--B
Content-Type: text/plain
Content-Length: 3
foo
--B
Content-Type: text/plain
Content-Length: 3
bar
and is typically paired with Transfer-Encoding: chunked
or Connection: close
to allow sending a response whose size is infinite or not known until
the end.
I can't find a good specification. This WHATWG
document
describes multipart/x-mixed-replace
loosely. It refers to RFC
2046 which defines multipart encodings
originally used for rich emails. I don't think these HTTP multipart streams
quite follow that RFC. My library currently requires:
multipart-stream
library.\r\n
sequences) between each part
and the next part's boundary.Content-Length
line for each part. This is a much cleaner approach
than producers attempting to choose a boundary that doesn't appear in any
part and consumers having to search through the part body.--
suffix on the final part's boundary. I've never seen one.Please open a github issue if you encounter a multipart stream which doesn't match these requirements.
It takes a stream of Bytes
(such as those returned by
reqwest or
hyper) and returns a stream of
multipart_stream::Part
s, or vice versa. (For client or server use cases,
respectively.) Each Part
packages together headers and a body.
Scott Lamb <slamb@slamb.org>
SPDX-License-Identifier: MIT OR Apache-2.0
See LICENSE-MIT.txt or LICENSE-APACHE, respectively.