Hi everyone,
I'm experiencing an issue with file uploads from a WASM module using the waki HTTP client. Small files work fine, but larger files cause the request to hang. I'm hoping someone might have insights into what's going wrong or if there are known limitations.
I'm implementing Google's resumable file upload API in a WASM module. The goal is to replicate this curl command:
# Upload the actual bytes.
curl "${upload_url}" \
-H "Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@${AUDIO_PATH}" 2> /dev/null > file_info.json
upload_request.send()?Here's the relevant code from my WASM module:
fn upload_file_and_get_uri(
client: &Client,
files_endpoint: &str,
api_key: &str,
audio_path: &Path,
file_size: u64,
mime_type: &str,
) -> Result<String> {
// Step 1: Initiate resumable upload (this works fine)
let init_request = client
.post(files_endpoint)
.header("x-goog-api-key", api_key)
.header("X-Goog-Upload-Protocol", "resumable")
.header("X-Goog-Upload-Command", "start")
.header("X-Goog-Upload-Header-Content-Length", &file_size.to_string())
.header("X-Goog-Upload-Header-Content-Type", mime_type)
.header("Content-Type", "application/json")
.body(serde_json::to_string(
&json!({ "file": { "display_name": "AUDIO" } }),
)?);
let init_response = init_request.send()?;
// ... get upload_url from response headers ...
// Step 2: Upload file (this is where it hangs for large files)
let file_bytes = fs::read(audio_path)?; // File read succeeds
println!("Creating client");
let upload_request = client
.post(&upload_url)
.header("Content-Length", &file_size.to_string())
.header("X-Goog-Upload-Offset", "0")
.header("X-Goog-Upload-Command", "upload, finalize")
.body(file_bytes); // 11.08 MB of data
println!("Making request");
let upload_response = upload_request.send()?; // <-- HANGS HERE for large file
println!("Received request response"); // Never reached for large file
// ... process response ...
}
The host setup includes proper WASI configuration:
let mut linker = Linker::<MyState>::new(&engine);
wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
wasmtime_wasi_http::add_only_http_to_linker_sync(&mut linker)?;
Has anyone encountered similar issues with large HTTP payloads in WASM modules? Any suggestions on alternative approaches or debugging strategies would be greatly appreciated!
Thanks in advance!
I am not familiar with waki and my best guess is that this is a bug in waki, without more context. Have you asked the waki maintainers to help you debug this?
also: I'd be debugging this interactively so you can jump into upload_request.send and see directly what happens
Thank you for the prompt response!
You were right to suspect a waki-specific issue. It turns out the problem was with the version of waki I was using. After updating to the latest version, the large file uploads (11MB+) now work perfectly without any code changes.
Hey @Utilize3214 could you elucidate more on the problem that waki had? I'm not familiar with waki at all, and still don't know what it is, but if it was a usage bug in the WASI toolchain/something upstream can make better to prevent bugs downstream, it might be useful to share the details or a link so interested parties can see what happened!
Debugging waki is almost certainly not on topic for this forum but helping embedders avoid bugs almost certainly is.
Hi @Victor Adossi, happy to share more details. waki is an HTTP client and server library designed for WebAssembly components using WASI, built specifically to work within WASI's constraints. From my understanding (though limited), the issue was related to how waki handled large HTTP request bodies when interfacing with wasi-http. It was fixed in this PR: https://github.com/wacker-dev/waki/pull/35. The PR description and code changes would give you a much better technical understanding than I can provide. Hope this helps.
Thanks for sharing!
Last updated: Dec 06 2025 at 06:05 UTC