@fastify/multipart
Advanced tools
Comparing version 8.2.0 to 8.3.0
42
index.js
@@ -29,2 +29,3 @@ 'use strict' | ||
const FileBufferNotFoundError = createError('FST_FILE_BUFFER_NOT_FOUND', 'the file buffer was not found', 500) | ||
const NoFormData = createError('FST_NO_FORM_DATA', 'FormData is not available', 500) | ||
@@ -127,4 +128,45 @@ function setMultipart (req, payload, done) { | ||
}) | ||
// The following is not available on old Node.js versions | ||
// so we must skip it in the test coverage | ||
/* istanbul ignore next */ | ||
if (globalThis.FormData && !fastify.hasRequestDecorator('formData')) { | ||
fastify.decorateRequest('formData', async function () { | ||
const formData = new FormData() | ||
for (const key in this.body) { | ||
const value = this.body[key] | ||
if (Array.isArray(value)) { | ||
for (const item of value) { | ||
await append(key, item) | ||
} | ||
} else { | ||
await append(key, value) | ||
} | ||
} | ||
async function append (key, entry) { | ||
if (entry.type === 'file' || (attachFieldsToBody === 'keyValues' && Buffer.isBuffer(entry))) { | ||
// TODO use File constructor with fs.openAsBlob() | ||
// if attachFieldsToBody is not set | ||
// https://nodejs.org/api/fs.html#fsopenasblobpath-options | ||
formData.append(key, new Blob([await entry.toBuffer()], { | ||
type: entry.mimetype | ||
}), entry.filename) | ||
} else { | ||
formData.append(key, entry.value) | ||
} | ||
} | ||
return formData | ||
}) | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
if (!fastify.hasRequestDecorator('formData')) { | ||
fastify.decorateRequest('formData', async function () { | ||
throw new NoFormData() | ||
}) | ||
} | ||
const defaultThrowFileSizeLimit = typeof options.throwFileSizeLimit === 'boolean' | ||
@@ -131,0 +173,0 @@ ? options.throwFileSizeLimit |
{ | ||
"name": "@fastify/multipart", | ||
"version": "8.2.0", | ||
"version": "8.3.0", | ||
"description": "Multipart plugin for Fastify", | ||
@@ -27,5 +27,2 @@ "main": "index.js", | ||
"eslint": "^8.20.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-n": "^16.0.1", | ||
"eslint-plugin-promise": "^6.0.0", | ||
"fastify": "^4.0.0", | ||
@@ -40,3 +37,3 @@ "form-data": "^4.0.0", | ||
"tap": "^16.0.0", | ||
"tsd": "^0.30.0" | ||
"tsd": "^0.31.0" | ||
}, | ||
@@ -43,0 +40,0 @@ "scripts": { |
@@ -238,2 +238,6 @@ # @fastify/multipart | ||
) // Request body in key-value pairs, like req.body in Express (Node 12+) | ||
// On Node 18+ | ||
const formData = await req.formData() | ||
console.log(formData) | ||
}) | ||
@@ -522,2 +526,3 @@ ``` | ||
- [LetzDoIt](https://www.letzdoitapp.com/) | ||
- [platformatic](https://platformatic.dev) | ||
@@ -524,0 +529,0 @@ ## License |
@@ -489,1 +489,56 @@ 'use strict' | ||
}) | ||
const hasGlobalFormData = typeof globalThis.FormData === 'function' | ||
test('should be able to attach all parsed fields and files and make it accessible through "req.formdata"', { skip: !hasGlobalFormData }, async function (t) { | ||
t.plan(10) | ||
const fastify = Fastify() | ||
t.teardown(fastify.close.bind(fastify)) | ||
fastify.register(multipart, { attachFieldsToBody: true }) | ||
const original = fs.readFileSync(filePath, 'utf8') | ||
fastify.post('/', async function (req, reply) { | ||
t.ok(req.isMultipart()) | ||
t.same(Object.keys(req.body), ['upload', 'hello']) | ||
const formData = await req.formData() | ||
t.equal(formData instanceof globalThis.FormData, true) | ||
t.equal(formData.get('hello'), 'world') | ||
t.same(formData.getAll('hello'), ['world', 'foo']) | ||
t.equal(await formData.get('upload').text(), original) | ||
t.equal(formData.get('upload').type, 'text/markdown') | ||
t.equal(formData.get('upload').name, 'README.md') | ||
reply.code(200).send() | ||
}) | ||
await fastify.listen({ port: 0 }) | ||
// request | ||
const form = new FormData() | ||
const opts = { | ||
protocol: 'http:', | ||
hostname: 'localhost', | ||
port: fastify.server.address().port, | ||
path: '/', | ||
headers: form.getHeaders(), | ||
method: 'POST' | ||
} | ||
const req = http.request(opts) | ||
form.append('upload', fs.createReadStream(filePath)) | ||
form.append('hello', 'world') | ||
form.append('hello', 'foo') | ||
form.pipe(req) | ||
const [res] = await once(req, 'response') | ||
t.equal(res.statusCode, 200) | ||
res.resume() | ||
await once(res, 'end') | ||
t.pass('res ended successfully') | ||
}) |
@@ -692,1 +692,48 @@ 'use strict' | ||
}) | ||
const hasGlobalFormData = typeof globalThis.FormData === 'function' | ||
test('no formData', { skip: !hasGlobalFormData }, function (t) { | ||
t.plan(6) | ||
const fastify = Fastify() | ||
t.teardown(fastify.close.bind(fastify)) | ||
fastify.register(multipart) | ||
fastify.post('/', async function (req, reply) { | ||
await t.rejects(req.formData()) | ||
for await (const part of req.parts()) { | ||
t.equal(part.type, 'field') | ||
t.equal(part.fieldname, 'hello') | ||
t.equal(part.value, 'world') | ||
} | ||
reply.code(200).send() | ||
}) | ||
fastify.listen({ port: 0 }, async function () { | ||
// request | ||
const form = new FormData() | ||
const opts = { | ||
protocol: 'http:', | ||
hostname: 'localhost', | ||
port: fastify.server.address().port, | ||
path: '/', | ||
headers: form.getHeaders(), | ||
method: 'POST' | ||
} | ||
const req = http.request(opts, (res) => { | ||
t.equal(res.statusCode, 200) | ||
// consume all data without processing | ||
res.resume() | ||
res.on('end', () => { | ||
t.pass('res ended successfully') | ||
}) | ||
}) | ||
form.append('hello', 'world') | ||
form.pipe(req) | ||
}) | ||
}) |
@@ -10,2 +10,4 @@ import { BusboyConfig, BusboyFileStream } from '@fastify/busboy' | ||
formData: () => Promise<FormData>; | ||
// promise api | ||
@@ -12,0 +14,0 @@ parts: ( |
@@ -27,2 +27,3 @@ import fastify from 'fastify' | ||
app.post('/', async (req, reply) => { | ||
expectType<Promise<FormData>>(req.formData()) | ||
const data = await req.file() | ||
@@ -29,0 +30,0 @@ if (data == null) throw new Error('missing file') |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
156535
20
192675
4477
530
1