Stream: wasi

Topic: Should GET + some(empty stream) be valid Request


view this post on Zulip Tomasz Andrzejak (May 15 2026 at 15:41):

Hey :wave:

I'm trying to understand the semantic difference in wasi/http between constructing a request with contents = none and constructing one with contents = some(stream) where the stream is later closed without yielding any values.

It looks like the wasmtime p3 http test helper always passes some(contents_rx) to Request::new, even for requests that are semantically body-less like GET or HEAD, and then simply writes no bytes for those cases:

https://github.com/bytecodealliance/wasmtime/blob/main/crates/test-programs/src/p3/http.rs#L73-L76

That means GET requests are constructed as Method::Get plus some(contents_rx), but with an empty stream.

I would have expected GET/HEAD with a non-null body argument to be invalid at construction or later at send time, similar to the Fetch Request constructor behavior:

If either init["body"] exists and is non-null or inputBody is non-null, and request's method is GET or HEAD, then throw a TypeError.

I think this distinction matters for host implementations because otherwise we need to drain/observe body streams for methods like GET/HEAD/CONNECT just to determine whether the request is invalid, instead of rejecting based on contents.is_some() which is fundamentally different from e.g.: https://fetch.spec.whatwg.org/#dom-request

Anyway, just wanted to confirm this is the intended behavior, thanks!

view this post on Zulip Pat Hickey (May 15 2026 at 23:25):

My best guess is that nobody thought this behavior through in detail yet.

view this post on Zulip Pat Hickey (May 15 2026 at 23:27):

I think that amending the spec with language like in Fetch, and the implementation to return the appropriate error when the request body is non-empty with GET/HEAD/CONNECT, is the right behavior.

view this post on Zulip Pat Hickey (May 15 2026 at 23:28):

Do you feel up for sending PRs to the spec, and the wasmtime implementation (including adding tests that the new behavior is followed, so that it gets picked up downstream by jco as well)?

view this post on Zulip Victor Adossi (May 16 2026 at 01:02):

I think that amending the spec with language like in Fetch, and the implementation to return the appropriate error when the request body is non-empty with GET/HEAD/CONNECT, is the right behavior.

So here I don't think we should follow what fetch does -- the HTTP spec is looser than what fetch allows (servers may accept GETs with bodies), and it is possible to send a fetch with a body from NodeJS, and it's possible to create a XMLHTTPRequest with a body in the browser (though it should be ignored, if browser is following the spec)

This comes as no surprise to anyone in this thread, but for those who are new long discussed issue, and one tension here is whether WASI should support as many use cases as possible (that exist now, in the wild) or be somewhat stricter here (as fetch has chosen to be).

view this post on Zulip Victor Adossi (May 16 2026 at 01:05):

Here was my response to Tomasz when we were chatting earlier (I didn't realize this discussion already existed!):

That said, this is likely a bug in the test program that we should consider changing/fixing? In the case of a truly streaming response (that happens to be empty) I think this problem is unavoidable, but the given body arg is actually an Option so we know whether there is a body or not.

Unfortunately, this doesn't actually change your dilemma -- it is possible that you will get an empty stream (for example if the component did not itself know the stream would be empty) from an arbitrary component.

Based on only the above IMO the right thing is to throw an error immediately if a body is present at all, regardless of what it produces, without watching the actual stream.

But that's only the case if we're forcing the use of fetch! XMLHTTPRequest has no such restriction, and of course NodeJS http has no such restriction. This may be a place where we have to fall back to other methods -- in particular XMLHTTPRequest will ignore the body if it's non-null.

So the tension here is whether we want to be strict with respect to fetch semantics or WASI semantics, and I think WASI wins out since it's more general/it's the main goal. That said, there is ambiguity here because what works in one environment may not work in another -- WASI does not/cannot guarantee that implementations act the same -- just that they have the same contract (and hopefully act the same) -- it's best effort AFAIK.

Like if you had some implementation that always errored on requests to any URL other than example.com. You could provide the API but it would just always error and not be portable.

Would love some feedback though to double-check my assumptions -- particularly on what WASI aims to guarantee/provide and cross platform differences. Obviously WASI tries incredibly hard to be consistent cross-platform but the realities of runtime (intentionally so, if you're restricting access of course) and what is realistically possible/what can be fully faithfully cross platform create tension there.

view this post on Zulip Tomasz Andrzejak (May 18 2026 at 08:25):

Hey, thanks both for your answer! The relevant part of RFC 9110 - HTTP Semantics says this:

https://www.rfc-editor.org/rfc/rfc9110.html#name-get

Although request message framing is independent of the method used, content received in a GET request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain

So I guess "SHOULD NOT generate" is different from saying that it is forbidden for GET to have content. If we allow creation of GET with content what should client do with such request: error, ignore or stream the content? Silently ignoring GET body feels wrong.

view this post on Zulip Victor Adossi (May 18 2026 at 11:59):

IMO what we should do in the case that we do accept GET requests with bodies is send the request with the GET (and body), or error if the host absolutely cannot for some reason


Last updated: Jun 01 2026 at 09:49 UTC