Skip to content

Instantly share code, notes, and snippets.

@billywhizz
Last active July 4, 2024 23:41
Show Gist options
  • Save billywhizz/db4ec9c6073c9ce7d8cba695c0f5ab73 to your computer and use it in GitHub Desktop.
Save billywhizz/db4ec9c6073c9ce7d8cba695c0f5ab73 to your computer and use it in GitHub Desktop.
bun repro

intro

if we run

bun simple.mjs
node simple.mjs
deno run -A simple.mjs

then the tests are all passing.

if we run

bun server.mjs

and then run

bun repro.mjs /

everything is ok

STATUS: 200 
CONTENT TYPE: text/plain;charset=utf-8
RAW BODY: {"name":"bbb"}

but if we run

bun repro.mjs /fail1

or

bun repro.mjs /fail2

or

bun repro.mjs /fail3

we see the error

STATUS: 500 
CONTENT TYPE: text/plain;charset=utf-8
RAW BODY: FormData parse error missing final boundary

if we use deno to run the server we don't see errors and get an empty json object back in all the cases where it fails for bun

deno run -A server.mjs
bun repro.mjs       

STATUS: 200 
CONTENT TYPE: text/plain;charset=UTF-8
RAW BODY: {"name":"bbb"}

bun repro.mjs /fail1
STATUS: 200 
CONTENT TYPE: text/plain;charset=UTF-8
RAW BODY: {}

bun repro.mjs /fail2 
STATUS: 200 
CONTENT TYPE: text/plain;charset=UTF-8
RAW BODY: {}

bun repro.mjs /fail3
STATUS: 200 
CONTENT TYPE: text/plain;charset=UTF-8
RAW BODY: {}

research

const path = Bun.argv[2] || '/'
const headers = new Headers();
headers.append("Content-Type", "multipart/form-data; boundary=abcd123");
const body = `--abcd123\r\nContent-Disposition: form-data; name="name"\r\n\r\nbbb\r\n--abcd123--\r\n`
const resp = await fetch(`http://localhost:3000${path}`, {
method: "POST",
headers,
body,
});
console.log(
"STATUS:",
resp.status,
"\nCONTENT TYPE:",
resp.headers.get("content-type"),
);
console.log("RAW BODY:", await resp.text());
async function handler(req, url) {
const contentType = req.headers.get("Content-Type")
if (!contentType) throw new Error("Missing Content-Type");
if (contentType.startsWith("multipart/form-data")) {
if (url.pathname === '/') {
const form_data = await req.formData()
const body = Object.fromEntries(form_data.entries());
return new Response(JSON.stringify(body))
} else if (url.pathname === '/fail1') {
const body = await (new Request(req, { ...req })).formData()
return new Response(JSON.stringify(body))
} else if (url.pathname === '/fail2') {
const body = await (new Request(req)).formData()
return new Response(JSON.stringify(body))
} else if (url.pathname === '/fail3') {
const body = await (new Request(req, { ...req, body: undefined })).formData()
return new Response(JSON.stringify(body))
} else {
throw new Error(`Bad path ${url.pathname}`)
}
}
throw new Error("Invalid Content-Type");
}
if (globalThis.Bun) {
Bun.serve({
port: 3000,
async fetch(request) {
try {
const url = new URL(request.url);
const response = await handler(request, url);
return response;
} catch (err) {
return new Response(err.message, { status: 500 });
}
}
})
} else if (globalThis.Deno) {
Deno.serve({ port: 3000 }, async (request) => {
try {
const url = new URL(request.url);
const response = await handler(request, url);
return response;
} catch (err) {
return new Response(err.message, { status: 500 });
}
})
}
const headers = new Headers();
headers.append("Content-Type", "multipart/form-data; boundary=abcd123");
async function test1 () {
const body = `--abcd123\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest1\r\n--abcd123--\r\n`
const req = new Request('http://localhost:3000/', {
method: 'POST',
headers,
body
})
try {
const form_data = await req.formData()
console.log(form_data)
console.log('test1 ok')
} catch (err) {
console.error(`test1 error ${err.message}`)
}
}
async function test2 () {
const body = `--abcd123\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest2\r\n--abcd123--\r\n`
const req = new Request('http://localhost:3000/', {
method: 'POST',
headers,
body
})
try {
const req2 = new Request(req)
const form_data = await req2.formData()
console.log(form_data)
console.log('test2 ok')
} catch (err) {
console.error(`test2 error ${err.message}`)
}
}
async function test3 () {
const body = `--abcd123\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest3\r\n--abcd123--\r\n`
const req = new Request('http://localhost:3000/', {
method: 'POST',
headers,
body
})
const contentType = req.headers.get("Content-Type")
if (!contentType) throw new Error("Missing Content-Type");
const url = new URL(req.url);
try {
const req2 = new Request(req, { ...req })
const form_data = await req2.formData()
console.log(form_data)
console.log('test3 ok')
} catch (err) {
console.error(`test3 error ${err.message}`)
}
}
await test1()
await test2()
await test3()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment