Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rebase: Generic Body Parser implemented #544

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9eb5ab4
chore: add support for OSSF scorecard reporting (#522)
inigomarquinez May 14, 2024
1c2f923
Added support for external parsers to bodyParser.json()
Nov 21, 2017
2f4913c
removed test dependency on json-bigint
Nov 21, 2017
6daefb5
reworked doc to describe json parser() func better
Nov 21, 2017
b740295
added parser() option and doc for .text()
Nov 21, 2017
cf3a8e3
added parser() option and doc for .raw()
Nov 21, 2017
2468f72
added parser() option and doc for .urlencoded()
Nov 21, 2017
d75adee
cleanup to satisfy linter
Nov 21, 2017
8224cda
added generic parser
Nov 21, 2017
a5adc82
converted json parser to use generic parser
Nov 21, 2017
c572330
converted raw parser to use generic parser
Nov 21, 2017
7390c89
converted text parser to use generic parser
Nov 21, 2017
f4f9d84
converted urlencoded parser to use generic parser
Nov 21, 2017
10eb0af
cleanup / fix linter warnings
Nov 21, 2017
67060ca
removed items from README
Nov 21, 2017
e6f6004
added bodyParser.generic() getter
Nov 21, 2017
07e0602
cleanup / fix linter warnings
Nov 21, 2017
bb7697a
fixed tests after rebase
sdellysse Apr 17, 2020
6a7c24d
satisfying linter
sdellysse Apr 17, 2020
bc7454b
Ref'd genParser via the bodyparser getter to signal how third party p…
sdellysse Apr 17, 2020
519f306
removed dep on object-assign, which didnt support node < 0.10
sdellysse Apr 17, 2020
cdf46f0
minor text cleanup
sdellysse Apr 17, 2020
8ac04fd
🔧 add debug script
ctcpip May 24, 2024
1a43910
🐛 fix object merging
ctcpip May 24, 2024
86804fe
🔥 clean up
ctcpip May 24, 2024
88f84bd
💚 remove node < 4 from CI
ctcpip May 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 2 additions & 27 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ jobs:
strategy:
matrix:
name:
- Node.js 0.10
- Node.js 0.12
- io.js 1.x
- io.js 2.x
- io.js 3.x
- Node.js 4.x
- Node.js 5.x
- Node.js 6.x
Expand All @@ -33,26 +28,6 @@ jobs:
- Node.js 19.x

include:
- name: Node.js 0.10
node-version: "0.10"
npm-i: [email protected] [email protected] [email protected]

- name: Node.js 0.12
node-version: "0.12"
npm-i: [email protected] [email protected] [email protected]

- name: io.js 1.x
node-version: "1.8"
npm-i: [email protected] [email protected] [email protected]

- name: io.js 2.x
node-version: "2.5"
npm-i: [email protected] [email protected] [email protected]

- name: io.js 3.x
node-version: "3.3"
npm-i: [email protected] [email protected] [email protected]

- name: Node.js 4.x
node-version: "4.9"
npm-i: [email protected] [email protected] [email protected]
Expand All @@ -71,11 +46,11 @@ jobs:

- name: Node.js 8.x
node-version: "8.17"
npm-i: mocha@7.2.0
npm-i: mocha@6.2.2 [email protected] [email protected]

- name: Node.js 9.x
node-version: "9.11"
npm-i: mocha@7.2.0
npm-i: mocha@6.2.2 [email protected] [email protected]

- name: Node.js 10.x
node-version: "10.24"
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.

name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '16 21 * * 1'
push:
branches: [ "master" ]

# Declare default permissions as read only.
permissions: read-all

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write

steps:
- name: "Checkout code"
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2
with:
persist-credentials: false

- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}

# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true

# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: SARIF file
path: results.sarif
retention-days: 5

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f # v2.23.2
with:
sarif_file: results.sarif
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,27 @@ specifies the number of bytes; if it is a string, the value is passed to the
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults
to `'100kb'`.

##### parser

The `parser` option is the function called against the request body to convert
it to a Javascript object. If a `reviver` is supplied, it is supplied as the
second argument to this function.

```
parser(body, reviver) -> req.body
```

Defaults to `JSON.parse`.

##### reviver

The `reviver` option is passed directly to `JSON.parse` as the second
argument. You can find more information on this argument
You can find more information on this argument
[in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter).

##### strict

When set to `true`, will only accept arrays and objects; when `false` will
accept anything `JSON.parse` accepts. Defaults to `true`.
accept anything the `parser` accepts. Defaults to `true`.

##### type

Expand Down Expand Up @@ -273,6 +284,16 @@ The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.

##### parser

The `parser` option, if supplied, is used to in place of the default parser to
convert the request body into a Javascript object. If this option is supplied,
both the `extended` and `parameterLimit` options are ignored.

```
parser(body) -> req.body
```

## Errors

The middlewares provided by this module create errors using the
Expand Down
14 changes: 14 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ Object.defineProperty(exports, 'urlencoded', {
get: createParserGetter('urlencoded')
})

/**
* Generic parser used to build parsers.
* @public
*/

Object.defineProperty(exports, 'generic', {
configurable: true,
enumerable: true,
get: createParserGetter('generic')
})

/**
* Create a middleware to parse json and urlencoded bodies.
*
Expand Down Expand Up @@ -123,6 +134,9 @@ function loadParser (parserName) {
case 'urlencoded':
parser = require('./lib/types/urlencoded')
break
case 'generic':
parser = require('./lib/generic-parser')
break
}

// store to prevent invoking require()
Expand Down
160 changes: 160 additions & 0 deletions lib/generic-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*!
* body-parser
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/

'use strict'

/**
* Module dependencies.
* @private
*/

var bytes = require('bytes')
var contentType = require('content-type')
var createError = require('http-errors')
var debug = require('debug')('body-parser:generic')
var isFinished = require('on-finished').isFinished
var read = require('./read')
var typeis = require('type-is')

/**
* Module exports.
*/

module.exports = generic

/**
* Use this to create a middleware that parses request bodies
*
* @param {object} [options]
* @return {function}
* @public
*/

function generic (parserOptions, parserOverrides) {
// Squash the options and the overrides down into one object
var opts = Object.create(parserOptions)
Object.assign(opts, parserOverrides)

var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var charset = opts.charset
var inflate = opts.inflate !== false
var verify = opts.verify || false
var parse = opts.parse || defaultParse
var defaultReqCharset = opts.defaultCharset || 'utf-8'
var type = opts.type

if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}

// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type

// create the appropriate charset validating function
var validCharset = typeof charset !== 'function'
? charsetValidator(charset)
: charset

return function genericParser (req, res, next) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}

if (!('body' in req)) {
req.body = undefined
}

// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}

debug('content-type %j', req.headers['content-type'])

// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}

// assert charset per RFC 7159 sec 8.1
var reqCharset = null
if (charset !== undefined) {
reqCharset = getCharset(req) || defaultReqCharset
if (!validCharset(reqCharset)) {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + reqCharset.toUpperCase() + '"', {
charset: reqCharset,
type: 'charset.unsupported'
}))
return
}
}

// read
read(req, res, next, parse, debug, {
encoding: reqCharset,
inflate: inflate,
limit: limit,
verify: verify
})
}
}

function defaultParse (buf) {
return buf
}

/**
* Get the charset of a request.
*
* @param {object} req
* @api private
*/

function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch (e) {
return undefined
}
}

/**
* Get the simple type checker.
*
* @param {string} type
* @return {function}
*/

function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
}

/**
* Get the simple charset validator.
*
* @param {string} type
* @return {function}
*/

function charsetValidator (charset) {
return function validateCharset (reqCharset) {
return charset === reqCharset
}
}
Loading
Loading