Skip to content

Commit c4a64e0

Browse files
committed
Implement per part Content-Length header support under enableAdditionalHeaders option.
1 parent c18264c commit c4a64e0

File tree

4 files changed

+213
-57
lines changed

4 files changed

+213
-57
lines changed

lib/FormDataEncoder.test.ts

Lines changed: 96 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ test("Yields correct footer for empty FormData", async t => {
147147
t.is(value, `--${encoder.boundary}--`)
148148
})
149149

150-
test("The footer ends with two crlf", async t => {
150+
test("The footer ends with double crlf", async t => {
151151
const actual = await readStream(new FormDataEncoder(new FormData()), true)
152152

153153
t.true(actual.endsWith("\r\n\r\n"))
@@ -161,36 +161,36 @@ test("Returns correct length of the empty FormData content", async t => {
161161
})
162162

163163
test("Returns the length of the FormData content", async t => {
164-
const fd = new FormData()
164+
const form = new FormData()
165165

166-
fd.set("field", "Some string")
167-
fd.set("file", new File(["Some content"], "file.txt"))
166+
form.set("field", "Some string")
167+
form.set("file", new File(["Some content"], "file.txt"))
168168

169-
const encoder = new FormDataEncoder(fd)
169+
const encoder = new FormDataEncoder(form)
170170

171171
const expected = await readStream(encoder).then(({length}) => length)
172172

173173
t.is<number>(encoder.getContentLength(), expected)
174174
})
175175

176176
test(".values() yields headers as Uint8Array", t => {
177-
const fd = new FormData()
177+
const form = new FormData()
178178

179-
fd.set("field", "Some value")
179+
form.set("field", "Some value")
180180

181-
const iterable = new FormDataEncoder(fd).values()
181+
const iterable = new FormDataEncoder(form).values()
182182

183183
const {value: actual} = skipSync(iterable)
184184

185185
t.true(actual instanceof Uint8Array)
186186
})
187187

188188
test(".valeus() yields field as Uint8Array", t => {
189-
const fd = new FormData()
189+
const form = new FormData()
190190

191-
fd.set("field", "Some value")
191+
form.set("field", "Some value")
192192

193-
const {value: actual} = skipSync(new FormDataEncoder(fd).values(), 2)
193+
const {value: actual} = skipSync(new FormDataEncoder(form).values(), 2)
194194

195195
t.true(actual instanceof Uint8Array)
196196
})
@@ -199,34 +199,34 @@ test(".valeus() yields field's content", t => {
199199
const string = "Some value"
200200
const expected = new TextEncoder().encode(string)
201201

202-
const fd = new FormData()
202+
const form = new FormData()
203203

204-
fd.set("field", string)
204+
form.set("field", string)
205205

206-
const {value: actual} = skipSync(new FormDataEncoder(fd).values(), 2)
206+
const {value: actual} = skipSync(new FormDataEncoder(form).values(), 2)
207207

208208
t.true(Buffer.from(actual as Uint8Array).equals(expected))
209209
})
210210

211211
test(".values() yields a file as is", async t => {
212212
const file = new File(["File content"], "name.txt")
213213

214-
const fd = new FormData()
214+
const form = new FormData()
215215

216-
fd.set("file", file)
216+
form.set("file", file)
217217

218-
const {value: actual} = skipSync(new FormDataEncoder(fd).values(), 2)
218+
const {value: actual} = skipSync(new FormDataEncoder(form).values(), 2)
219219

220220
t.true(actual instanceof File)
221221
t.is(await (actual as File).text(), await file.text())
222222
})
223223

224224
test("Yields correct headers for a field", async t => {
225-
const fd = new FormData()
225+
const form = new FormData()
226226

227-
fd.set("field", "Some value")
227+
form.set("field", "Some value")
228228

229-
const iterable = readLine(Readable.from(new FormDataEncoder(fd)))
229+
const iterable = readLine(Readable.from(new FormDataEncoder(form)))
230230

231231
const {value} = await skip(iterable, 2)
232232

@@ -236,25 +236,25 @@ test("Yields correct headers for a field", async t => {
236236
test("Yields field's content", async t => {
237237
const expected = "Some value"
238238

239-
const fd = new FormData()
239+
const form = new FormData()
240240

241-
fd.set("field", expected)
241+
form.set("field", expected)
242242

243243
const {
244244
value
245-
} = await skip(readLine(Readable.from(new FormDataEncoder(fd))), 4)
245+
} = await skip(readLine(Readable.from(new FormDataEncoder(form))), 4)
246246

247247
t.is(value, expected)
248248
})
249249

250250
test("Yields Content-Disposition header for a File", async t => {
251-
const fd = new FormData()
251+
const form = new FormData()
252252

253-
fd.set("file", new File(["My hovercraft is full of eels"], "file.txt"))
253+
form.set("file", new File(["My hovercraft is full of eels"], "file.txt"))
254254

255255
const {
256256
value
257-
} = await skip(readLine(Readable.from(new FormDataEncoder(fd))), 2)
257+
} = await skip(readLine(Readable.from(new FormDataEncoder(form))), 2)
258258

259259
t.is(
260260
value,
@@ -263,43 +263,81 @@ test("Yields Content-Disposition header for a File", async t => {
263263
})
264264

265265
test("Yields Content-Type header for a File", async t => {
266-
const fd = new FormData()
266+
const form = new FormData()
267267

268-
fd.set("file", new File(["My hovercraft is full of eels"], "file.txt", {
268+
form.set("file", new File(["My hovercraft is full of eels"], "file.txt", {
269269
type: "text/plain"
270270
}))
271271

272272
const {
273273
value
274-
} = await skip(readLine(Readable.from(new FormDataEncoder(fd))), 3)
274+
} = await skip(readLine(Readable.from(new FormDataEncoder(form))), 3)
275275

276276
t.is(value, "Content-Type: text/plain")
277277
})
278278

279279
test(
280280
"File has default Content-Type set to application/octet-stream",
281281
async t => {
282-
const fd = new FormData()
282+
const form = new FormData()
283283

284-
fd.set("file", new File(["Some content"], "file"))
284+
form.set("file", new File(["Some content"], "file"))
285285

286-
const iterable = readLine(Readable.from(new FormDataEncoder(fd)))
286+
const iterable = readLine(Readable.from(new FormDataEncoder(form)))
287287

288288
const {value} = await skip(iterable, 3)
289289

290290
t.is(value, "Content-Type: application/octet-stream")
291291
}
292292
)
293293

294+
test(
295+
"Yields Content-Length File header when enableAdditionalHeaders option is on",
296+
297+
async t => {
298+
const form = new FormData()
299+
const file = new File(["Some content"], "file")
300+
301+
form.set("file", file)
302+
303+
const iterable = readLine(Readable.from(new FormDataEncoder(form, {
304+
enableAdditionalHeaders: true
305+
})))
306+
307+
const {value} = await skip(iterable, 4)
308+
309+
t.is(value, `Content-Length: ${file.size}`)
310+
}
311+
)
312+
313+
test(
314+
"Yields Content-Length header when enableAdditionalHeaders option is on",
315+
316+
async t => {
317+
const form = new FormData()
318+
const field = "Some value"
319+
320+
form.set("field", field)
321+
322+
const iterable = readLine(Readable.from(new FormDataEncoder(form, {
323+
enableAdditionalHeaders: true
324+
})))
325+
326+
const {value} = await skip(iterable, 3)
327+
328+
t.is(value, `Content-Length: ${Buffer.byteLength(field)}`)
329+
}
330+
)
331+
294332
test("Yields File's content", async t => {
295333
const filePath = "license"
296-
const fd = new FormData()
334+
const form = new FormData()
297335

298336
const expected = await fs.readFile(filePath, "utf-8")
299337

300-
fd.set("license", await fileFromPath(filePath))
338+
form.set("license", await fileFromPath(filePath))
301339

302-
const encoder = new FormDataEncoder(fd)
340+
const encoder = new FormDataEncoder(form)
303341
const iterable = readLine(Readable.from(encoder))
304342

305343
await skip(iterable, 4)
@@ -322,12 +360,12 @@ test("Yields File's content", async t => {
322360
test("Yields every appended field", async t => {
323361
const expectedDisposition = "Content-Disposition: form-data; name=\"field\""
324362

325-
const fd = new FormData()
363+
const form = new FormData()
326364

327-
fd.append("field", "Some string")
328-
fd.append("field", "Some other string")
365+
form.append("field", "Some string")
366+
form.append("field", "Some other string")
329367

330-
const iterable = readLine(Readable.from(new FormDataEncoder(fd)))
368+
const iterable = readLine(Readable.from(new FormDataEncoder(form)))
331369

332370
const {value: firstFieldDisposition} = await skip(iterable, 2)
333371

@@ -349,17 +387,17 @@ test("Yields every appended field", async t => {
349387
test("Yields every appended File", async t => {
350388
const expectedDisposition = "Content-Disposition: form-data; name=\"file\""
351389

352-
const fd = new FormData()
390+
const form = new FormData()
353391

354392
const firstFile = new File(["Some content"], "file.txt", {type: "text/plain"})
355393
const secondFile = new File(["Some **content**"], "file.md", {
356394
type: "text/markdown"
357395
})
358396

359-
fd.append("file", firstFile)
360-
fd.append("file", secondFile)
397+
form.append("file", firstFile)
398+
form.append("file", secondFile)
361399

362-
const iterable = readLine(Readable.from(new FormDataEncoder(fd)))
400+
const iterable = readLine(Readable.from(new FormDataEncoder(form)))
363401

364402
const {value: firstFileDisposition} = await skip(iterable, 2)
365403

@@ -387,12 +425,12 @@ test("Yields every appended File", async t => {
387425
})
388426

389427
test("Can be read through using Blob", async t => {
390-
const fd = new FormData()
428+
const form = new FormData()
391429

392-
fd.set("field", "Some field")
393-
fd.set("file", await fileFromPath("license", {type: "text/plain"}))
430+
form.set("field", "Some field")
431+
form.set("file", await fileFromPath("license", {type: "text/plain"}))
394432

395-
const encoder = new FormDataEncoder(fd)
433+
const encoder = new FormDataEncoder(form)
396434
const blob = new Blob([...encoder] as any[])
397435

398436
t.true(
@@ -421,6 +459,16 @@ test("Throws TypeError when given boundary is not a string", t => {
421459

422460
t.throws(trap, {
423461
instanceOf: TypeError,
424-
message: "Expected boundary to be a string."
462+
message: "Expected boundary argument to be a string."
463+
})
464+
})
465+
466+
test("Throws TypeError when options argument is not an object", t => {
467+
// @ts-expect-error
468+
const trap = () => new FormDataEncoder(new FormData(), undefined, "451")
469+
470+
t.throws(trap, {
471+
instanceOf: TypeError,
472+
message: "Expected options argument to be an object."
425473
})
426474
})

0 commit comments

Comments
 (0)