librespeed / librespeed/speedtest-rust

Upload requests with Transfer-Encoding: chunked hang forever

Open
#49 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
249
Forks
37
PR merge metrics
No merged PRs in 30d

Description

Summary

The hand-written HTTP parser never chunk-decodes request bodies: BodyType::Chunked (src/http/request.rs) reads the raw stream in fixed 1024-byte read_exact blocks until EOF. With a finite payload the client keeps the connection open (keep-alive, no half-close), the final block never fills, and the server blocks forever instead of answering.

Impact

Any client that sends Transfer-Encoding: chunked stalls after its first payload. Concrete case: librespeed/speedtest-cli#122 — librespeed-cli v1.0.13+ uploads at 0.55 Mbps against librespeed-rs 1.4.0:

  • The Go client wraps the upload body in a counting io.TeeReader which hides its length, so it sends chunked.
  • Server log from a replica of this body handling: CHUNKED: read 1048837 raw bytes, then EOF/blocked — 1024×1024 payload + 261 bytes of chunk framing; 1048837 is not a multiple of 1024, so the last read_exact(1024) blocks waiting for 763 more bytes that never come.
  • Upload rate = one payload / default 15 s duration = 1 MiB / 15 s ≈ 0.55 Mbps.

Same stall applies to curl -H "Transfer-Encoding: chunked" --data-binary @file and any chunked uploader. Content-Length requests (BodyType::Fixed) work fine.

Suggested fix

Parse chunked encoding in the Chunked branch (RFC 9112 §7.1): read the chunk-size line, the chunk data, and the terminating CRLF per chunk; stop at a 0-size chunk and consume the trailer section. Tokio's BufReader (already in use) provides lines() and read_exact for this.

Client-side note

librespeed/speedtest-cli now sends Content-Length for its fixed-size uploads (librespeed/speedtest-cli#143) as a workaround, but fixing chunked handling here makes the server robust for all clients.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/http/request.rs at the BodyType::Chunked branch and review how the existing Tokio BufReader reads request bodies. Reproduce a finite chunked upload over a keep-alive connection, then verify that chunk data, the terminating CRLF, and trailers are consumed and the request completes instead of waiting for EOF.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend, networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.