Right now the server will always send back a chunked response because the Response type always creates a stream for handling the response. I did this because it's easy to implement, doesn't affect the public API and doesn't really impact performance, but it's not correct and I want to implement the correct logic.
For context, Go will automatically determine if a response should be a Transfer-Encoding: chunked verses a static "one shot" response.
I want to imitate that logic. Go decides this based on a few factors.
- If the
Transfer-Encoding: chunked is set before writeHead then it will be chunked
- If the internal 4k buffer fills up, it will be chunked
- If the response is written in a go routine, it will be chunked
- If
Flush is manually called, it will be chunked
- Some other rules I need to investigate
In Rust;
- We can hook into the
Drop for Response
- If there are multiple references to
Response, then it has been cloned and should be chunked
- Maybe this is bad as you could spin up a task that completes before the handler completes
- Might be a good idea to change the public API to something like:
let mut writer = res.write_head_chunked() so it's explicit.
- We can hook into
AsyncWrite.flush to immediately convert to a chunked response.
- If we have already called
write_head
- We can hook into
AsyncWrite.write to determine
- If we have called
write_head and
- if we have exceeded the buffer size and convert to a chunked response.
Experimentation here: https://github.com/alshdavid-public/uhttp/blob/chunked-encoding/crates/uhttp/src/http/response.rs
I've added tests. It's messy but it sort of works.
My issue is that calling flush does convert to a chunked response but on single threaded/concurrent servers, the response buffer doesn't send as the first chunked response.
This is because the tx_send (sending back the builder) won't fire until the flush poll has completed.
Right now the server will always send back a chunked response because the
Responsetype always creates a stream for handling the response. I did this because it's easy to implement, doesn't affect the public API and doesn't really impact performance, but it's not correct and I want to implement the correct logic.For context, Go will automatically determine if a response should be a
Transfer-Encoding: chunkedverses a static "one shot" response.I want to imitate that logic. Go decides this based on a few factors.
Transfer-Encoding: chunkedis set beforewriteHeadthen it will be chunkedFlushis manually called, it will be chunkedIn Rust;
DropforResponseResponse, then it has been cloned and should be chunkedlet mut writer = res.write_head_chunked()so it's explicit.AsyncWrite.flushto immediately convert to a chunked response.write_headAsyncWrite.writeto determinewrite_headandExperimentation here: https://github.com/alshdavid-public/uhttp/blob/chunked-encoding/crates/uhttp/src/http/response.rs
I've added tests. It's messy but it sort of works.
My issue is that calling
flushdoes convert to a chunked response but on single threaded/concurrent servers, the response buffer doesn't send as the first chunked response.This is because the
tx_send(sending back the builder) won't fire until theflushpoll has completed.