🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

formidable

Package Overview
Dependencies
Maintainers
5
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

formidable - npm Package Compare versions

Comparing version

to
2.1.3

36

package.json
{
"name": "formidable",
"version": "2.1.2",
"version": "2.1.3",
"license": "MIT",

@@ -33,4 +33,4 @@ "description": "A node.js module for parsing form data, especially file uploads.",

"dependencies": {
"@paralleldrive/cuid2": "^2.2.2",
"dezalgo": "^1.0.4",
"hexoid": "^1.0.0",
"once": "^1.4.0",

@@ -40,4 +40,2 @@ "qs": "^6.11.0"

"devDependencies": {
"@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.3.4",
"@tunnckocore/prettier-config": "1.3.8",

@@ -52,5 +50,4 @@ "del-cli": "3.0.0",

"husky": "4.2.5",
"jest": "25.4.0",
"jest": "27.2.4",
"koa": "2.11.0",
"lint-staged": "10.2.7",
"make-dir-cli": "2.0.0",

@@ -75,28 +72,3 @@ "nyc": "15.0.1",

"file"
],
"husky": {
"hooks": {
"pre-commit": "git status --porcelain && yarn lint-staged",
"commit-msg": "yarn commitlint -E HUSKY_GIT_PARAMS"
}
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"lint-staged": {
"!*.{js,jsx,ts,tsx}": [
"yarn run fmt:prepare"
],
"*.{js,jsx,ts,tsx}": [
"yarn run lint"
]
},
"renovate": {
"extends": [
"@tunnckocore",
":pinAllExceptPeerDependencies"
]
}
]
}

173

README.md

@@ -5,10 +5,21 @@ <p align="center">

# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url]
# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url]
> A Node.js module for parsing form data, especially file uploads.
> [!CAUTION] As of April 2025, old versions like v1 and v2 are still the most
> used, while they are deperecated for years -- they are also vulnerable to
> attacks if you are not implementing it properly. **Please upgrade!** We are
> here to help, and AI Editors & Agents could help a lot in such codemod-like
> migrations.
> [!TIP] If you are starting a fresh project, try `formidable@latest` (v3) or
> you can check out the `formidable-mini` which is a super minimal version of
> Formidable (not quite configurable yet, but when it does it could become the
> basis for `formidable@v4`), using web standards like FormData API and File
> API, and you can use it to stream uploads directly to S3 or other such
> services.
[![Code style][codestyle-img]][codestyle-url]
[![codecoverage][codecov-img]][codecov-url]
[![linux build status][linux-build-img]][build-url]
[![windows build status][windows-build-img]][build-url]
[![macos build status][macos-build-img]][build-url]

@@ -19,13 +30,19 @@

documents.<br /> For bugs reports and feature requests, [please create an
issue][open-issue-url] or ping [@tunnckoCore / @3a1FcBx0](https://twitter.com/3a1FcBx0)
at Twitter.
issue][open-issue-url] or ping
[@wgw_eth / @wgw_lol](https://twitter.com/wgw_eth) at Twitter.
[![Conventional Commits][ccommits-img]][ccommits-url]
[![Minimum Required Nodejs][nodejs-img]][npmv-url]
[![Buy me a Kofi][kofi-img]][kofi-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
[![Twitter][twitter-img]][twitter-url]
<!-- [![Conventional Commits][ccommits-img]][ccommits-url]
[![Minimum Required Nodejs][nodejs-img]][npmv-url]
[![Tidelift Subcsription][tidelift-img]][tidelift-url]
[![Buy me a Kofi][kofi-img]][kofi-url]
[![Renovate App Status][renovateapp-img]][renovateapp-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url] -->
This project is [semantically versioned](https://semver.org) and available as
<!-- This project is [semantically versioned](https://semver.org) and available as
part of the [Tidelift Subscription][tidelift-url] for professional grade

@@ -39,3 +56,3 @@ assurances, enhanced support and security.

improve code health, while paying the maintainers of the exact dependencies you
use._
use._ -->

@@ -47,3 +64,5 @@ [![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url]

_Check [VERSION NOTES](https://github.com/node-formidable/formidable/blob/master/VERSION_NOTES.md) for more information on v1, v2, and v3 plans, NPM dist-tags and branches._
_Check
[VERSION NOTES](https://github.com/node-formidable/formidable/blob/master/VERSION_NOTES.md)
for more information on v1, v2, and v3 plans, NPM dist-tags and branches._

@@ -80,3 +99,5 @@ This module was initially developed by

This is a low-level package, and if you're using a high-level framework it _may_
already be included. Check the examples below and the [examples/](https://github.com/node-formidable/formidable/tree/master/examples) folder.
already be included. Check the examples below and the
[examples/](https://github.com/node-formidable/formidable/tree/master/examples)
folder.

@@ -93,5 +114,5 @@ ```sh

_**Note:** In near future v3 will be published on the `latest` NPM dist-tag. Future not ready releases will continue to be published on `canary` dist-tag._
_**Note:** In near future v3 will be published on the `latest` NPM dist-tag.
Future not ready releases will continue to be published on `canary` dist-tag._
## Examples

@@ -334,8 +355,9 @@

limit the size of uploaded file.
- `options.maxFields` **{number}** - default `1000`; limit the number of fields, set 0 for unlimited
- `options.maxFields` **{number}** - default `1000`; limit the number of fields,
set 0 for unlimited
- `options.maxFieldsSize` **{number}** - default `20 * 1024 * 1024` (20mb);
limit the amount of memory all fields together (except files) can allocate in
bytes.
- `options.hashAlgorithm` **{string | false}** - default `false`; include checksums calculated
for incoming files, set this to some hash algorithm, see
- `options.hashAlgorithm` **{string | false}** - default `false`; include
checksums calculated for incoming files, set this to some hash algorithm, see
[crypto.createHash](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options)

@@ -364,5 +386,4 @@ for available algorithms

#### `options.filename` **{function}** function (name, ext, part, form) -> string
#### `options.filename` **{function}** function (name, ext, part, form) -> string
_**Note:** If this size of combined fields, or size of some file is exceeded, an

@@ -381,16 +402,15 @@ `'error'` event is fired._

#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean
#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean
**Note:** use an outside variable to cancel all uploads upon the first error
**Note:** use an outside variable to cancel all uploads upon the first error
```js
const options = {
filter: function ({name, originalFilename, mimetype}) {
filter: function ({ name, originalFilename, mimetype }) {
// keep only images
return mimetype && mimetype.includes("image");
}
return mimetype && mimetype.includes('image');
},
};
```
### .parse(request, callback)

@@ -417,3 +437,4 @@

About `uploadDir`, given the following directory structure
About `uploadDir`, given the following directory structure
```

@@ -423,3 +444,3 @@ project-name

│ └── server.js
└── uploads

@@ -431,5 +452,4 @@ └── image.jpg

```js
`${__dirname}/../uploads`
`${__dirname}/../uploads`;
```

@@ -439,13 +459,14 @@

Omitting `__dirname` would make the path relative to the current working directory. This would be the same if server.js is launched from src but not project-name.
Omitting `__dirname` would make the path relative to the current working
directory. This would be the same if server.js is launched from src but not
project-name.
`null` will use default which is `os.tmpdir()`
Note: If the directory does not exist, the uploaded files are __silently discarded__. To make sure it exists:
Note: If the directory does not exist, the uploaded files are **silently
discarded**. To make sure it exists:
```js
import {createNecessaryDirectoriesSync} from "filesac";
import { createNecessaryDirectoriesSync } from 'filesac';
const uploadPath = `${__dirname}/../uploads`;

@@ -455,3 +476,2 @@ createNecessaryDirectoriesSync(`${uploadPath}/x`);

In the example below, we listen on couple of events and direct them to the

@@ -485,26 +505,29 @@ `data` listener, so you can do whatever you choose there, based on whether its

// If you want to customize whatever you want...
form.on('data', ({ name, key, value, buffer, start, end, formname, ...more }) => {
if (name === 'partBegin') {
}
if (name === 'partData') {
}
if (name === 'headerField') {
}
if (name === 'headerValue') {
}
if (name === 'headerEnd') {
}
if (name === 'headersEnd') {
}
if (name === 'field') {
console.log('field name:', key);
console.log('field value:', value);
}
if (name === 'file') {
console.log('file:', formname, value);
}
if (name === 'fileBegin') {
console.log('fileBegin:', formname, value);
}
});
form.on(
'data',
({ name, key, value, buffer, start, end, formname, ...more }) => {
if (name === 'partBegin') {
}
if (name === 'partData') {
}
if (name === 'headerField') {
}
if (name === 'headerValue') {
}
if (name === 'headerEnd') {
}
if (name === 'headersEnd') {
}
if (name === 'field') {
console.log('field name:', key);
console.log('field value:', value);
}
if (name === 'file') {
console.log('file:', formname, value);
}
if (name === 'fileBegin') {
console.log('fileBegin:', formname, value);
}
},
);
```

@@ -621,3 +644,3 @@

file.originalFilename: string | null;
// calculated based on options provided

@@ -672,8 +695,8 @@ file.newFilename: string | null;

form.on('fileBegin', (formName, file) => {
// accessible here
// formName the name in the form (<input name="thisname" type="file">) or http filename for octetstream
// file.originalFilename http filename or null if there was a parsing error
// file.newFilename generated hexoid or what options.filename returned
// file.filepath default pathnme as per options.uploadDir and options.filename
// file.filepath = CUSTOM_PATH // to change the final path
// accessible here
// formName the name in the form (<input name="thisname" type="file">) or http filename for octetstream
// file.originalFilename http filename or null if there was a parsing error
// file.newFilename generated hexoid or what options.filename returned
// file.filepath default pathnme as per options.uploadDir and options.filename
// file.filepath = CUSTOM_PATH // to change the final path
});

@@ -689,5 +712,5 @@ ```

form.on('file', (formname, file) => {
// same as fileBegin, except
// it is too late to change file.filepath
// file.hash is available if options.hash was used
// same as fileBegin, except
// it is too late to change file.filepath
// file.hash is available if options.hash was used
});

@@ -787,4 +810,6 @@ ```

- [Sven Lito](https://github.com/svnlto) for fixing bugs and merging patches
- [egirshov](https://github.com/egirshov) for contributing many improvements to the node-formidable multipart parser
- [Andrew Kelley](https://github.com/superjoe30) for also helping with fixing bugs and making improvements
- [egirshov](https://github.com/egirshov) for contributing many improvements to
the node-formidable multipart parser
- [Andrew Kelley](https://github.com/superjoe30) for also helping with fixing
bugs and making improvements
- [Mike Frey](https://github.com/mikefrey) for contributing JSON support

@@ -817,4 +842,4 @@

[prs-welcome-url]: http://makeapullrequest.com
[twitter-url]: https://twitter.com/3a1fcBx0
[twitter-img]: https://badgen.net/twitter/follow/3a1fcBx0?icon=twitter&color=1da1f2&cache=300
[twitter-url]: https://twitter.com/wgw_eth
[twitter-img]: https://badgen.net/badge/twitter/follow/wgw_eth?icon=twitter&color=1da1f2&cache=30

@@ -842,6 +867,6 @@ [npm-weekly-img]: https://badgen.net/npm/dw/formidable?icon=npm&cache=300

[linux-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/ubuntu?cache=300&label=linux%20build&icon=github
[macos-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/macos?cache=300&label=macos%20build&icon=github
[linux-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master?label=linux%20build&icon=github
[macos-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master?label=macos%20build&icon=github
[windows-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/windows?cache=300&label=windows%20build&icon=github
[build-url]: https://github.com/node-formidable/formidable/actions?query=workflow%3Anodejs
[build-url]: https://github.com/node-formidable/formidable/actions
<!-- prettier-ignore-end -->

@@ -8,3 +8,3 @@ /* eslint-disable class-methods-use-this */

const path = require('path');
const hexoid = require('hexoid');
const cuid2 = require('@paralleldrive/cuid2');
const once = require('once');

@@ -16,3 +16,10 @@ const dezalgo = require('dezalgo');

const toHexoId = hexoid(25);
const CUID2_FINGERPRINT = `${
process.env.NODE_ENV
}-${os.platform()}-${os.hostname()}-${os.machine()}`;
const createId = cuid2.init({
length: 25,
fingerprint: CUID2_FINGERPRINT.toLowerCase(),
});
const DEFAULT_OPTIONS = {

@@ -32,3 +39,3 @@ maxFields: 1000,

defaultInvalidName: 'invalid-name',
filter: function () {
filter() {
return true;

@@ -547,4 +554,2 @@ },

_joinDirectoryName(name) {

@@ -578,11 +583,12 @@ const newPath = path.join(this.uploadDir, name);

this._getNewName = (part) => {
const name = toHexoId();
const name = createId();
if (part && this.options.keepExtensions) {
const originalFilename = typeof part === 'string' ? part : part.originalFilename;
const originalFilename =
typeof part === 'string' ? part : part.originalFilename;
return `${name}${this._getExtension(originalFilename)}`;
}
return name;
}
};
}

@@ -589,0 +595,0 @@ }