Skip to content

Commit

Permalink
fix(fetch): allow third-party FormData/Blob bodies
Browse files Browse the repository at this point in the history
`webidl.converters.XMLHttpRequestBodyInit` rejected third-party
`FormData`/`Blob`s, meaning they were passed through
`webidl.converters.DOMString`. This meant `Request`/`Response`s
constructed with third-party `FormData`/`Blob` bodies ended up with a
plain-text `[object FormData]`/`[object Blob]` body.
  • Loading branch information
mrbbot committed Sep 11, 2022
1 parent 0862fba commit 5c2ca96
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
6 changes: 3 additions & 3 deletions lib/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ webidl.converters.XMLHttpRequestBodyInit = function (V) {
}

if (isBlobLike(V)) {
return webidl.converters.Blob(V)
return webidl.converters.Blob(V, { strict: false })
}

if (
Expand All @@ -530,8 +530,8 @@ webidl.converters.XMLHttpRequestBodyInit = function (V) {
return webidl.converters.BufferSource(V)
}

if (V instanceof FormData) {
return webidl.converters.FormData(V)
if (util.isFormDataLike(V)) {
return webidl.converters.FormData(V, { strict: false })
}

if (V instanceof URLSearchParams) {
Expand Down
24 changes: 24 additions & 0 deletions test/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const {
fetch
} = require('../../')
const { kState } = require('../../lib/fetch/symbols.js')
const {
Blob: ThirdPartyBlob,
FormData: ThirdPartyFormData
} = require('formdata-node')
const hasSignalReason = !!~process.version.localeCompare('v16.14.0', undefined, { numeric: true })

test('arg validation', async (t) => {
Expand Down Expand Up @@ -435,3 +439,23 @@ test('RequestInit.signal option', async (t) => {
signal: false
}), TypeError)
})

test('constructing Request with third party Blob body', async (t) => {
const blob = new ThirdPartyBlob(['text'])
const req = new Request('http://asd', {
method: 'POST',
body: blob
})
t.equal(await req.text(), 'text')
})
test('constructing Request with third party FormData body', async (t) => {
const form = new ThirdPartyFormData()
form.set('key', 'value')
const req = new Request('http://asd', {
method: 'POST',
body: form
})
const contentType = req.headers.get('content-type').split('=')
t.equal(contentType[0], 'multipart/form-data; boundary')
t.ok((await req.text()).startsWith(`--${contentType[1]}`))
})
18 changes: 18 additions & 0 deletions test/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const {
Response
} = require('../../')
const { ReadableStream } = require('stream/web')
const {
Blob: ThirdPartyBlob,
FormData: ThirdPartyFormData
} = require('formdata-node')

test('arg validation', async (t) => {
// constructor
Expand Down Expand Up @@ -230,3 +234,17 @@ test('constructing a Response with a ReadableStream body', async (t) => {

t.end()
})

test('constructing Response with third party Blob body', async (t) => {
const blob = new ThirdPartyBlob(['text'])
const res = new Response(blob)
t.equal(await res.text(), 'text')
})
test('constructing Response with third party FormData body', async (t) => {
const form = new ThirdPartyFormData()
form.set('key', 'value')
const res = new Response(form)
const contentType = res.headers.get('content-type').split('=')
t.equal(contentType[0], 'multipart/form-data; boundary')
t.ok((await res.text()).startsWith(`--${contentType[1]}`))
})

0 comments on commit 5c2ca96

Please sign in to comment.