Open Dominaezzz opened 1 week ago
multipart/x-mixed-replace
seems very different to regular HTTP requests and responses, even things like SSE and websockets, so I don't think that I want an implementation in picoserve itself.
Originally I decided to be relatively restrictive with what sorts of responses could be produced, hence Response having private fields, and Response::new requiring a body of Content
, which requires a known length and MIME type, as opposed to the more general Body
, with no such restrictions. This was both for developer ergonomics, in that it avoided footguns to do with forgetting to send the relevant headers, but also helped prevent me coding myself into a corner and having major breaking changes.
However, now that picoserve has been out for a while with a relatively stable structure, and that I've implemented support for automatically handing the "Connection" header and Keep-Alive, it seems a good time to provide functionality to create unusual responses that don't follow the standard pattern.
Thus, I introduce the CustomBody
trait and CustomResponse
struct, similar to SSE, WebSockets, and Chunked Transfer Encoding. You should be able to implement multipart/x-mixed-replace
on top of it.
It's currently in the development
branch, let me know if it works for you!
Yes CustomBody
and CustomResponse
let me implement multipart/x-mixed-replace
. I just tried it and it works like a charm.
Now that Connection
is no longer a parameter of write_content
, how can I tell when the connection is closed? I used to have some cleanup logic with wait_for_disconnect
.
Is your cleanup login sync or async? If sync, can your CustomBody
implement Drop
?
Ah sorry, I misrepresented my problem. My clean up logic is sync but even if I implement Drop, when I cancel the stream in the browser, the server hangs and hits a write timeout. During this hang time I can't handle more requests.
Ideally I'd like the write to be cancelled immediately, which I was previously doing myself by calling connection.wait_for_disconnect().
This is needed to implement an MJPEG stream. A typical multipart response looks something like this.
At the moment I can't implement this outside the library because the
Content
trait mandates that I provide acontent_length()
and I don't think there's any public way to create a (custom)Response
without aContent-Length
header. So I guess this has to implemented inside the library similar to SSE and WebSockets? I'm imagining something like theEventStream
struct, AMixedReplace
struct that takes two parameters, a boundary string and aContentSource
trait. TheContentSource
trait just allows the user to write newContent
s. (I'm not 100% sure ifContent
is the right trait for this, was just my first thought)Side note: Firefox seems to not mind a
Content-Length
atm, so specifying a value like1000000
allows me to workaround this issue while developing and I'm able to stream small JPEGs with this.(This library is fantastic btw! Thanks for building it and sharing it!)