Closed minwidth0px closed 1 month ago
One thing I've noticed is that ---REQUEST_END---
is not being received in Firefox. I determined this by logging the following in HttpListener
:
#createReadableFromRequestInit(listenerRequestInit, stream) {
if (["HEAD", "GET"].includes(listenerRequestInit.method))
return null;
return new ReadableStream({
pull: async (controller) => {
const next = await stream.read();
console.log("next", next);
console.log(new TextDecoder().decode(next));
if (next === null || equals(next, REQUEST_END)) {
return controller.close();
} else {
console.log("enquing...")
controller.enqueue(next);
}
}
});
}
Firefox:
90796fb9-32ed-4283-86a5-ced092338fe4
next Uint8Array(17) [ 123, 34, 104, 101, 108, 108, 111, 34, 58, 34, … ]
{"hello":"world"}
enquing...
Object { body: "[object ReadableStream]" }
Chrome:
456908b4-1f55-4f7b-92ba-ae65969530dc
next Uint8Array(17) [123, 34, 104, 101, 108, 108, 111, 34, 58, 34, 119, 111, 114, 108, 100, 34, 125, buffer: ArrayBuffer(17), byteLength: 17, byteOffset: 0, length: 17, Symbol(Symbol.toStringTag): 'Uint8Array']
{"hello":"world"}
enquing...
next Uint8Array(17) [45, 45, 45, 82, 69, 81, 85, 69, 83, 84, 95, 69, 78, 68, 45, 45, 45, buffer: ArrayBuffer(17), byteLength: 17, byteOffset: 0, length: 17, Symbol(Symbol.toStringTag): 'Uint8Array']
---REQUEST_END---
{body: '{"hello":"world"}'}
Note how in Firefox ---REQUEST_END--- is never printed. This means controller.close is never called, although I don't know what the implications of that are, and maybe there is some other affect ---REQUEST_END--- is meant to have and that is causing the issue, or maybe this is a completely unrelated bug. But it's another difference between Firefox and Chrome in any event.
@minwidth0px Hi,
Object { body: "[object ReadableStream]" }
So this issue appears to related to how Firefox implements the Request
API. The offending code is below.
https://github.com/sinclairzx81/smoke/blob/master/src/http/listener.mts#L136-L142
// Read the body as a ReadableStream
const body = this.#createReadableFromRequestInit(listenerRequestInit, stream)
// Pass the ReadableStream to Request
const request = new Request(url, {
method: listenerRequestInit.method,
headers: headers,
body: body, // Body is a ReadableStream
duplex: 'half',
} as RequestInit)
// Expect .text() to asynchronously read from the ReadableStream.
const text = await request.text() // this function should asynchronously read from the ReadableStream
// assigned to the `body`, not return `[object ReadableStream]`
So, there isn't much that can be done here (afaik) other than polyfill / patching the Request prototype in Firefox (something I am very reluctant to do) or outright reimplementing Request from scratch (also extremely reluctant to do)
Maybe there is a specification write up on Request that would give an indication on what .text() "should do" if the assigned body is a ReadableStream? If there is a specification on what the correct implementation is, I'd be willing to align Smoke to that, but yeah, the Firefox implementation seems at odds with expectations.
Relevant Firefox Issue (With the issue dating back several years)
@sinclairzx81 so the ---REQUEST_END--- thing is unrelated?
@sinclairzx81 so the ---REQUEST_END--- thing is unrelated?
Not sure, just looking into it
So, there isn't much that can be done here (afaik) other than polyfill / patching the Request prototype in Firefox (something I am very reluctant to do) or outright reimplementing Request from scratch (also extremely reluctant to do)
Agreed that it may not be worth it if Firefox is not following the spec here.
Since this is a Firefox bug I'm going to close this issue. This does mean that Firefox doesn't work for post requests now (I think), but it seems like this bug may be fixed soon actually, according to the linked bug report. I may hack some bad solution in the meantime on my local project (obviously will not make a PR for that). We can open a new bug for the ---REQUEST_END--- thing if that is a separate issue.
@minwidth0px I've implemented a fix that should resolve both REQUEST_END
and Firefox .text()
issues.
The current solution appears to be to assign Firefox Requests a Blob
instead of ReadableStream
. Have setup a code path for that that runs in Firefox only.
Fix is on 0.8.7
confirmed that it is working on 0.8.7 on Firefox. You can't stream responses from a Firefox server, although I assume that is just a limitation of using blob instead of stream (as implied by the name). Hopefully that bug is fixed soon and we can remove this workaround.
Here's a minimal example (tested on @sinclair/smoke@0.8.5, as per
npm list
)This is a simple variation of the sample project in #21.
results:
Firefox:
Chrome:
This isn't just a formatting thing and actually shows up in errors (eg. 'unexpected value "[o"' )
I also tested the server and client on Chrome and Firefox separately, and found that the issue is on the server side of Firefox. Using chrome as the server and Firefox as the client returns
{body: '{"hello":"world"}'}
. I tested this behavior on separate browsers using two separate files like so:a.mts:
a.html:
b.mts:
b.html:
I'm going to look into the cause of this issue, but I thought I'd report it now and respond to this post when I find the cause. (Not sure if I should keep all Firefox issues in #24, but I didn't want to clutter it with random bugs. Let me know what is better.)