Socket
Socket
Sign inDemoInstall

@fastify/multipart

Package Overview
Dependencies
Maintainers
18
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fastify/multipart - npm Package Compare versions

Comparing version 7.0.0 to 7.1.0

2

index.d.ts

@@ -153,3 +153,3 @@ import { Busboy, BusboyConfig, BusboyFileStream } from "@fastify/busboy";

*/
attachFieldsToBody: true
attachFieldsToBody: true | 'keyValues';

@@ -156,0 +156,0 @@ /**

@@ -123,3 +123,3 @@ 'use strict'

if (options.attachFieldsToBody === true) {
if (options.attachFieldsToBody === true || options.attachFieldsToBody === 'keyValues') {
if (typeof options.sharedSchemaId === 'string') {

@@ -151,2 +151,14 @@ fastify.addSchema({

}
if (options.attachFieldsToBody === 'keyValues') {
const body = {}
for (const key of Object.keys(req.body)) {
const field = req.body[key]
if (field.value !== undefined) {
body[key] = field.value
} else if (field._buf !== undefined) {
body[key] = field._buf.toString()
}
}
req.body = body
}
})

@@ -153,0 +165,0 @@ }

{
"name": "@fastify/multipart",
"version": "7.0.0",
"version": "7.1.0",
"description": "Multipart plugin for Fastify",

@@ -9,3 +9,3 @@ "main": "index.js",

"@fastify/busboy": "^1.0.0",
"@fastify/error": "^2.0.0",
"@fastify/error": "^3.0.0",
"deepmerge": "^4.2.2",

@@ -22,2 +22,3 @@ "end-of-stream": "^1.4.4",

"climem": "^1.0.3",
"concat-stream": "^2.0.0",
"eslint": "^7.7.0",

@@ -30,3 +31,3 @@ "eslint-config-standard": "^16.0.0",

"eslint-plugin-typescript": "^0.14.0",
"fastify": "^4.0.0-rc.2",
"fastify": "^4.0.0",
"form-data": "^4.0.0",

@@ -33,0 +34,0 @@ "h2url": "^0.2.0",

@@ -5,3 +5,2 @@ # @fastify/multipart

[![NPM version](https://img.shields.io/npm/v/@fastify/multipart.svg?style=flat)](https://www.npmjs.com/package/@fastify/multipart)
[![Known Vulnerabilities](https://snyk.io/test/github/fastify/fastify-multipart/badge.svg)](https://snyk.io/test/github/fastify/fastify-multipart)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)

@@ -227,3 +226,3 @@

This allows you to parse all fields automatically and assign them to the `request.body`. By default files are accumulated in memory (Be careful!) to buffer objects. Uncaught errors are [handled](https://github.com/fastify/fastify/blob/master/docs/Hooks.md#manage-errors-from-a-hook) by Fastify.
This allows you to parse all fields automatically and assign them to the `request.body`. By default files are accumulated in memory (Be careful!) to buffer objects. Uncaught errors are [handled](https://github.com/fastify/fastify/blob/main/docs/Reference/Hooks.md#manage-errors-from-a-hook) by Fastify.

@@ -242,2 +241,13 @@ ```js

Request body key-value pairs can be assigned directly using `attachFieldsToBody: 'keyValues'`. Field values will be attached directly to the body object. By default, all files are converted to a string using `buffer.toString()` used as the value attached to the body.
```js
fastify.register(require('@fastify/multipart'), { attachFieldsToBody: 'keyValues' })
fastify.post('/upload/files', async function (req, reply) {
const uploadValue = req.body.upload // access file as string
const fooValue = req.body.foo // other fields
})
```
You can also define an `onFile` handler to avoid accumulating all files in memory.

@@ -257,2 +267,19 @@

The `onFile` handler can also be used with `attachFieldsToBody: 'keyValues'` in order to specify how file buffer values are decoded.
```js
async function onFile(part) {
const buff = await part.toBuffer()
const decoded = Buffer.from(buff.toString(), 'base64').toString()
part.value = decoded // set `part.value` to specify the request body value
}
fastify.register(require('@fastify/multipart'), { attachFieldsToBody: 'keyValues', onFile })
fastify.post('/upload/files', async function (req, reply) {
const uploadValue = req.body.upload // access file as base64 string
const fooValue = req.body.foo // other fields
})
```
**Note**: if you assign all fields to the body and don't define an `onFile` handler, you won't be able to read the files through streams, as they are already read and their contents are accumulated in memory.

@@ -264,5 +291,35 @@ You can only use the `toBuffer` method to read the content.

If you enable `attachFieldsToBody` and set `sharedSchemaId` a shared JSON Schema is added, which can be used to validate parsed multipart fields.
If you enable `attachFieldsToBody: 'keyValues'` then the response body and JSON Schema validation will behave similarly to `application/json` and [`application/x-www-form-urlencoded`](https://github.com/fastify/fastify-formbody) content types. Files will be decoded using `Buffer.toString()` and attached as a body value.
```js
fastify.register(require('@fastify/multipart'), { attachFieldsToBody: 'keyValues' })
fastify.post('/upload/files', {
schema: {
body: {
type: 'object',
required: ['myFile'],
properties: {
// file that gets decoded to string
myFile: {
type: 'string',
// validate that file contents match a UUID
pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
},
hello: {
type: 'string',
enum: ['world']
}
}
}
}
}, function (req, reply) {
console.log({ body: req.body })
reply.send('done')
})
```
If you enable `attachFieldsToBody: true` and set `sharedSchemaId` a shared JSON Schema is added, which can be used to validate parsed multipart fields.
```js
const opts = {

@@ -269,0 +326,0 @@ attachFieldsToBody: true,

@@ -33,3 +33,3 @@ 'use strict'

t.equal(part.encoding, '7bit')
t.equal(part.mimetype, 'binary/octect-stream')
t.equal(part.mimetype, 'binary/octet-stream')

@@ -72,3 +72,3 @@ await sendToWormhole(part.file)

filename: 'random-data',
contentType: 'binary/octect-stream',
contentType: 'binary/octet-stream',
knownLength

@@ -75,0 +75,0 @@ })

@@ -21,3 +21,3 @@ import fastify from 'fastify'

// stream should be of type streams.Readable
// body should be of type fastifyMulipart.Record<string, BodyEntry>
// body should be of type fastifyMultipart.Record<string, BodyEntry>
onFile: (fieldName: string, stream: any, filename: string, encoding: string, mimetype: string, body: Record<string, any>) => {

@@ -24,0 +24,0 @@ console.log(fieldName, stream, filename, encoding, mimetype, body)

@@ -38,3 +38,3 @@ 'use strict'

t.equal(encoding, '7bit')
t.equal(mimetype, 'binary/octect-stream')
t.equal(mimetype, 'binary/octet-stream')
const hashOutput = crypto.createHash('sha256')

@@ -92,3 +92,3 @@

filename: 'random-data',
contentType: 'binary/octect-stream',
contentType: 'binary/octet-stream',
knownLength

@@ -95,0 +95,0 @@ })

@@ -11,2 +11,3 @@ 'use strict'

const { once } = require('events')
const { Readable } = require('stream')

@@ -63,2 +64,147 @@ const filePath = path.join(__dirname, '../README.md')

test('should be able to attach all parsed field values and json content files and make it accessible through "req.body"', async function (t) {
t.plan(6)
const fastify = Fastify()
t.teardown(fastify.close.bind(fastify))
fastify.register(multipart, { attachFieldsToBody: 'keyValues' })
const original = { testContent: 'test upload content' }
fastify.post('/', async function (req, reply) {
t.ok(req.isMultipart())
t.same(Object.keys(req.body), ['upload', 'hello'])
t.same(req.body.upload, original)
t.equal(req.body.hello, 'world')
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', Readable.from(Buffer.from(JSON.stringify(original))), { contentType: 'application/json' })
form.append('hello', 'world')
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')
})
test('should be able to attach all parsed field values and files and make it accessible through "req.body"', async function (t) {
t.plan(6)
const fastify = Fastify()
t.teardown(fastify.close.bind(fastify))
fastify.register(multipart, { attachFieldsToBody: 'keyValues' })
const original = fs.readFileSync(filePath, 'utf8')
fastify.post('/', async function (req, reply) {
t.ok(req.isMultipart())
t.same(Object.keys(req.body), ['upload', 'hello'])
t.equal(req.body.upload, original)
t.equal(req.body.hello, 'world')
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.pipe(req)
const [res] = await once(req, 'response')
t.equal(res.statusCode, 200)
res.resume()
await once(res, 'end')
t.pass('res ended successfully')
})
test('should be able to attach all parsed field values and files with custom "onFile" handler and make it accessible through "req.body"', async function (t) {
t.plan(7)
const fastify = Fastify()
t.teardown(fastify.close.bind(fastify))
async function onFile (part) {
t.pass('custom onFile handler')
const buff = await part.toBuffer()
const decoded = Buffer.from(buff.toString(), 'base64').toString()
part.value = decoded
}
fastify.register(multipart, { attachFieldsToBody: 'keyValues', onFile })
const original = 'test upload content'
fastify.post('/', async function (req, reply) {
t.ok(req.isMultipart())
t.same(Object.keys(req.body), ['upload', 'hello'])
t.equal(req.body.upload, original)
t.equal(req.body.hello, 'world')
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', Readable.from(Buffer.from(original).toString('base64')))
form.append('hello', 'world')
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')
})
test('should be able to define a custom "onFile" handler', async function (t) {

@@ -65,0 +211,0 @@ t.plan(7)

@@ -72,3 +72,3 @@ 'use strict'

filename: 'random-data',
contentType: 'binary/octect-stream',
contentType: 'binary/octet-stream',
knownLength

@@ -75,0 +75,0 @@ })

@@ -13,3 +13,2 @@ 'use strict'

const { access } = require('fs').promises
const rimraf = require('rimraf')
const EventEmitter = require('events')

@@ -249,3 +248,3 @@ const { once } = EventEmitter

// temp file saved, remove before the onResponse hook
rimraf.sync(tmpdir)
await fs.promises.rm(tmpdir, { recursive: true, force: true })
reply.code(200).send()

@@ -345,3 +344,3 @@ } catch (error) {

filename: 'random-data',
contentType: 'binary/octect-stream',
contentType: 'binary/octet-stream',
knownLength

@@ -460,3 +459,3 @@ })

filename: 'random-data',
contentType: 'binary/octect-stream',
contentType: 'binary/octet-stream',
knownLength

@@ -463,0 +462,0 @@ })

@@ -34,3 +34,3 @@ 'use strict'

filename: 'random-data',
contentType: 'binary/octect-stream',
contentType: 'binary/octet-stream',
knownLength

@@ -37,0 +37,0 @@ })

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc