aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/body-parser/lib/read.js
diff options
context:
space:
mode:
authorpack <pack@packgekko.xyz>2026-08-09 10:37:07 +0000
committerpack <pack@packgekko.xyz>2026-08-09 10:37:07 +0000
commit55a4f1fc869e41aca748c63d3018f0448b1606e0 (patch)
treed132d1d01772b6d53faee3e63c534dea5706b78a /node_modules/body-parser/lib/read.js
downloadcrud-55a4f1fc869e41aca748c63d3018f0448b1606e0.tar.gz
first commit
Diffstat (limited to 'node_modules/body-parser/lib/read.js')
-rw-r--r--node_modules/body-parser/lib/read.js247
1 files changed, 247 insertions, 0 deletions
diff --git a/node_modules/body-parser/lib/read.js b/node_modules/body-parser/lib/read.js
new file mode 100644
index 0000000..bf1a1df
--- /dev/null
+++ b/node_modules/body-parser/lib/read.js
@@ -0,0 +1,247 @@
+/*!
+ * body-parser
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+const createError = require('http-errors')
+const getBody = require('raw-body')
+const iconv = require('iconv-lite')
+const onFinished = require('on-finished')
+const zlib = require('node:zlib')
+const hasBody = require('type-is').hasBody
+const { getCharset } = require('./utils')
+
+/**
+ * Module exports.
+ */
+
+module.exports = read
+
+/**
+ * Read a request into a buffer and parse.
+ *
+ * @param {Object} req
+ * @param {Object} res
+ * @param {Function} next
+ * @param {Function} parse
+ * @param {Function} debug
+ * @param {Object} options
+ * @private
+ */
+function read (req, res, next, parse, debug, options) {
+ if (onFinished.isFinished(req)) {
+ debug('body already parsed')
+ next()
+ return
+ }
+
+ if (!('body' in req)) {
+ req.body = undefined
+ }
+
+ // skip requests without bodies
+ if (!hasBody(req)) {
+ debug('skip empty body')
+ next()
+ return
+ }
+
+ debug('content-type %j', req.headers['content-type'])
+
+ // determine if request should be parsed
+ if (!options.shouldParse(req)) {
+ debug('skip parsing')
+ next()
+ return
+ }
+
+ let encoding = null
+ if (options?.skipCharset !== true) {
+ encoding = getCharset(req) || options.defaultCharset
+
+ // validate charset
+ if (!!options?.isValidCharset && !options.isValidCharset(encoding)) {
+ debug('invalid charset')
+ next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
+ charset: encoding,
+ type: 'charset.unsupported'
+ }))
+ return
+ }
+ }
+
+ let length
+ const opts = options
+ let stream
+
+ // read options
+ const verify = opts.verify
+
+ try {
+ // get the content stream
+ stream = contentstream(req, debug, opts.inflate)
+ length = stream.length
+ stream.length = undefined
+ } catch (err) {
+ return next(err)
+ }
+
+ // set raw-body options
+ opts.length = length
+ opts.encoding = verify
+ ? null
+ : encoding
+
+ // assert charset is supported
+ if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) {
+ return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
+ charset: encoding.toLowerCase(),
+ type: 'charset.unsupported'
+ }))
+ }
+
+ // read body
+ debug('read body')
+ getBody(stream, opts, function (error, body) {
+ if (error) {
+ let _error
+
+ if (error.type === 'encoding.unsupported') {
+ // echo back charset
+ _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
+ charset: encoding.toLowerCase(),
+ type: 'charset.unsupported'
+ })
+ } else {
+ // set status code on error
+ _error = createError(400, error)
+ }
+
+ // unpipe from stream and destroy
+ if (stream !== req) {
+ req.unpipe()
+ stream.destroy()
+ }
+
+ // read off entire request
+ dump(req, function onfinished () {
+ next(createError(400, _error))
+ })
+ return
+ }
+
+ // verify
+ if (verify) {
+ try {
+ debug('verify body')
+ verify(req, res, body, encoding)
+ } catch (err) {
+ next(createError(403, err, {
+ body: body,
+ type: err.type || 'entity.verify.failed'
+ }))
+ return
+ }
+ }
+
+ // parse
+ let str = body
+ try {
+ debug('parse body')
+ str = typeof body !== 'string' && encoding !== null
+ ? iconv.decode(body, encoding)
+ : body
+ req.body = parse(str, encoding)
+ } catch (err) {
+ next(createError(400, err, {
+ body: str,
+ type: err.type || 'entity.parse.failed'
+ }))
+ return
+ }
+
+ next()
+ })
+}
+
+/**
+ * Get the content stream of the request.
+ *
+ * @param {Object} req
+ * @param {Function} debug
+ * @param {boolean} inflate
+ * @returns {Object}
+ * @private
+ */
+function contentstream (req, debug, inflate) {
+ const encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
+ const length = req.headers['content-length']
+
+ debug('content-encoding "%s"', encoding)
+
+ if (inflate === false && encoding !== 'identity') {
+ throw createError(415, 'content encoding unsupported', {
+ encoding: encoding,
+ type: 'encoding.unsupported'
+ })
+ }
+
+ if (encoding === 'identity') {
+ req.length = length
+ return req
+ }
+
+ const stream = createDecompressionStream(encoding, debug)
+ req.pipe(stream)
+ return stream
+}
+
+/**
+ * Create a decompression stream for the given encoding.
+ * @param {string} encoding
+ * @param {Function} debug
+ * @returns {Object}
+ * @private
+ */
+function createDecompressionStream (encoding, debug) {
+ switch (encoding) {
+ case 'deflate':
+ debug('inflate body')
+ return zlib.createInflate()
+ case 'gzip':
+ debug('gunzip body')
+ return zlib.createGunzip()
+ case 'br':
+ debug('brotli decompress body')
+ return zlib.createBrotliDecompress()
+ default:
+ throw createError(415, 'unsupported content encoding "' + encoding + '"', {
+ encoding: encoding,
+ type: 'encoding.unsupported'
+ })
+ }
+}
+
+/**
+ * Dump the contents of a request.
+ *
+ * @param {Object} req
+ * @param {Function} callback
+ * @private
+ */
+function dump (req, callback) {
+ if (onFinished.isFinished(req)) {
+ callback(null)
+ } else {
+ onFinished(req, callback)
+ req.resume()
+ }
+}