Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing req.body.tee results in attempting to access detached ArrayBuffer #329

Open
radu-matei opened this issue Feb 7, 2025 · 3 comments
Labels
bug Something isn't working
Milestone

Comments

@radu-matei
Copy link
Member

Repro is a simple function that tees the request body stream; one is forwarded to an upstream (upstream is /api/upstream, needs to be allow-listed in spin.toml), the other stream is logged:

import { AutoRouter } from 'itty-router';

let router = AutoRouter();

router
    .post('/api/tee', async (req) => {
        console.log('[tee]: received request to tee');
        const [forwardStream, logStream] = req.body!.tee();

        const forwardRequest = new Request('http://localhost:3000/api/upstream', { body: forwardStream, method: req.method });

        const response = await fetch(forwardRequest);

        await logRequestBody(logStream);

        return response;
    })

    .post('/api/upstream', async (req) => {
        console.log(`[forwarded]: ${await req.text()}`)

        return new Response('Successfully forwarded', { status: 200 })
    })

async function logRequestBody(stream: any) {
    const reader = stream.getReader();
    const chunks = [];
    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        chunks.push(value);
    }
    const fullArray = concatChunks(chunks);
    // Decode the Uint8Array into a UTF-8 string.
    const text = new TextDecoder("utf-8").decode(fullArray);
    console.log(`[tee]: Logged request body: ${text}`);
}

function concatChunks(chunks: any) {
    const totalLength = chunks.reduce((sum: any, chunk: any) => sum + chunk.length, 0);
    const result = new Uint8Array(totalLength);
    let offset = 0;
    for (const chunk of chunks) {
        result.set(chunk, offset);
        offset += chunk.length;
    }
    return result;
}

//@ts-ignore
addEventListener('fetch', async (event: FetchEvent) => { event.respondWith(router.fetch(event.request)) });

This results in the following error sent to the client:

* upload completely sent off: 36 bytes
< HTTP/1.1 500 Internal Server Error
< content-length: 66
< content-type: application/json; charset=utf-8
< date: Fri, 07 Feb 2025 20:05:02 GMT
<
* Connection #0 to host localhost left intact
{"status":500,"error":"attempting to access detached ArrayBuffer"}%
@radu-matei
Copy link
Member Author

ref #330

@karthik2804
Copy link
Collaborator

I believe there is a fix in progress upstream for this in StarlingMonkey. cc: @tschneidereit

@tschneidereit
Copy link
Collaborator

Correct, yes: this should be fixed by bytecodealliance/StarlingMonkey#210, for which I added a regression test based on the code here.

@tschneidereit tschneidereit added this to the Version 3.2 milestone Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants