Skip to content

Auto Chunked response vs one-shot response #10

Description

@alshdavid

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions