trim21 / gm-fetch

fetch API for `GM.xmlHttpRequest`
MIT License
19 stars 2 forks source link

GM.xmlHttpRequest fails in Chrome with TypeError: Failed to construct 'Headers' Invalid value #162

Open turkishmaid opened 1 month ago

turkishmaid commented 1 month ago

Description

GM.xmlHttpRequest fails in Chrome with TypeError: Failed to construct 'Headers' Invalid value. It turns out that this piece of code splits a header string by \r\n while the header string h comes in with only \n as line separator:

var GM_fetch = (function () {
    'use strict';

    function parseRawHeaders(h) {
        const s = h.trim();
        if (!s) {
            return new Headers();
        }
        const array = s.split("\r\n").map((value) => {  
            let s = value.split(":");
            return [s[0].trim(), s[1].trim()];
        });
        return new Headers(array);
    }

Environment

How to reproduce

const res = await GM_fetch("http://127.0.0.1:4711/test");

Expectations

Should deal with the headers as they come in, i.e. regardless whether it's \r\n (Brave 👍) or just \n (Chrome 🤦🏼‍♀️). The following simple patch will do:

var GM_fetch = (function () {
    'use strict';

    function parseRawHeaders(h) {
        const s = h.trim().replace(/\r\n/g, '\n');          // patch
        if (!s) {
            return new Headers();
        }
        // const array = s.split("\r\n").map((value) => {   // original
        const array = s.split("\n").map((value) => {        // patch
            let s = value.split(":");
            return [s[0].trim(), s[1].trim()];
        });
        return new Headers(array);
    }

Should be here:

https://github.com/trim21/gm-fetch/blob/c377b28f827d2cd65f7da9bff8dfb1a90066bce1/src/utils.ts#L7

but I'm not the TypeScript expert to PR for that. In fact, I don't even have TS set up on my machine.

Actual result

GM.xmlHttpRequest fails with TypeError: Failed to construct 'Headers' Invalid value.

trim21 commented 1 month ago

HTTP RFC says line break must be CRLF.

HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all protocol elements except the entity-body (see appendix 19.3 for tolerant applications). The end-of-line marker within an entity-body is defined by its associated media type, as described in section 3.7.

trim21 commented 1 month ago

I'm using chrome on windows, which OS you are using?

Is this issue platform specific?

Or can you share server code to reproduce this? python/nodejs/go would be best.

turkishmaid commented 1 month ago

HTTP RFC says line break must be CRLF

Absolutely! That's why I was using the respective emoticons above.

can you share server code

Unfortunately, no. It happens in userscript context in the browser. Let me give you a MVE to play with it yourself (use whatever URL you like for the GM_fetch, it will fail anyway):

// ==UserScript==
// @name         trim21
// @match        https://www.example.com/
// @require      https://cdn.jsdelivr.net/npm/@trim21/gm-fetch@0.1.15/dist/gm_fetch.js
// @grant        GM.xmlHttpRequest
// @connect      *
// @run-at       document-end
// ==/UserScript==

await( async () => {
    'use strict';
    const url = "https://www.example.com";
    console.info(`will fetch ${url}`)
    // will fail with TypeError: Failed to construct 'Headers': Invalid value
    const res = await GM_fetch(url, {
        headers: { "content-type": "text/html" },
    });
    const text = await res.rawBody.text();
    console.info(text);
})();

Will break like so when you load https://www.example.com/:

162-3

162-4

You can see the value already in the debugger preview:

accept-ranges:bytes\nage:516377\ncache-control:max-age=
                  ====        ====

Nb.: It's the response headers, not the request headers, and it's completely independent from the URL you are fetching...

turkishmaid commented 1 month ago

Oh, apologies, forgot the first question: I'm on MacOS 14.4 (23E214)...

trim21 commented 1 month ago

It doesn't reproduce on windows. I think this is a upstream issue from Tampermonkey, can you also send a issue to them?

I can add a workaround on macos, but I think this should be fixed my Tampermonkey, since RFC says it's CRLF.

trim21 commented 1 month ago

you can send a PR to add a workaround for MacOS only.

subbotinb commented 6 days ago

I have the same error on Windows with the latest version of Tampermonkey.

you can send a PR to add a workaround for MacOS only. you can send a PR to add a workaround for MacOS only.

trim21 commented 6 days ago

this should have been fixed by upstream https://github.com/Tampermonkey/tampermonkey/issues/2160