Socket
Socket
Sign inDemoInstall

raw-body

Package Overview
Dependencies
Maintainers
2
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

raw-body - npm Package Compare versions

Comparing version 1.3.4 to 2.0.0

7

HISTORY.md

@@ -0,1 +1,8 @@

2.0.0 / 2015-05-08
==================
* Return a promise without callback instead of thunk
* deps: bytes@2.0.1
- units no longer case sensitive when parsing
1.3.4 / 2015-04-15

@@ -2,0 +9,0 @@ ==================

309

index.js

@@ -0,8 +1,61 @@

/*!
* raw-body
* Copyright(c) 2013-2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict'
/**
* Module dependencies.
* @private
*/
var bytes = require('bytes')
var iconv = require('iconv-lite')
module.exports = function (stream, options, done) {
/**
* Module exports.
* @public
*/
module.exports = getRawBody
/**
* Get the decoder for a given encoding.
*
* @param {string} encoding
* @private
*/
function getDecoder(encoding) {
if (!encoding) return null
try {
return iconv.getCodec(encoding).decoder()
} catch (e) {
var err = makeError('specified encoding unsupported', 'encoding.unsupported')
err.status = err.statusCode = 415
err.encoding = encoding
throw err
}
}
/**
* Get the raw body of a stream (typically HTTP).
*
* @param {object} stream
* @param {object|string|function} [options]
* @param {function} [callback]
* @public
*/
function getRawBody(stream, options, callback) {
var done = callback
var opts = options || {}
if (options === true || typeof options === 'string') {
// short cut for encoding
options = {
opts = {
encoding: options

@@ -12,26 +65,106 @@ }

options = options || {}
if (typeof options === 'function') {
done = options
options = {}
opts = {}
}
// validate callback is a function, if provided
if (done !== undefined && typeof done !== 'function') {
throw new TypeError('argument callback must be a function')
}
// require the callback without promises
if (!done && !global.Promise) {
throw new TypeError('argument callback is required')
}
// get encoding
var encoding = options.encoding !== true
? options.encoding
var encoding = opts.encoding !== true
? opts.encoding
: 'utf-8'
// convert the limit to an integer
var limit = null
if (typeof options.limit === 'number')
limit = options.limit
if (typeof options.limit === 'string')
limit = bytes(options.limit)
var limit = typeof opts.limit === 'number' ? opts.limit
: typeof opts.limit === 'string' ? bytes(opts.limit)
: null
// convert the expected length to an integer
var length = null
if (options.length != null && !isNaN(options.length))
length = parseInt(options.length, 10)
var length = opts.length != null && !isNaN(opts.length)
? parseInt(opts.length, 10)
: null
if (done) {
// classic callback style
return readStream(stream, encoding, length, limit, done)
}
return new Promise(function executor(resolve, reject) {
readStream(stream, encoding, length, limit, function onRead(err, buf) {
if (err) return reject(err)
resolve(buf)
})
})
}
/**
* Halt a stream.
*
* @param {Object} stream
* @private
*/
function halt(stream) {
// unpipe everything from the stream
unpipe(stream)
// pause stream
if (typeof stream.pause === 'function') {
stream.pause()
}
}
/**
* Make a serializable error object.
*
* To create serializable errors you must re-set message so
* that it is enumerable and you must re configure the type
* property so that is writable and enumerable.
*
* @param {string} message
* @param {string} type
* @param {object} props
* @private
*/
function makeError(message, type, props) {
var error = new Error()
for (var prop in props) {
error[prop] = props[prop]
}
error.message = message
Object.defineProperty(error, 'type', {
value: type,
enumerable: true,
writable: true,
configurable: true
})
return error
}
/**
* Read the data from the stream.
*
* @param {object} stream
* @param {string} encoding
* @param {number} length
* @param {number} limit
* @param {function} callback
* @public
*/
function readStream(stream, encoding, length, limit, callback) {
// check the length and limit options.

@@ -41,12 +174,13 @@ // note: we intentionally leave the stream paused,

if (limit !== null && length !== null && length > limit) {
var err = makeError('request entity too large', 'entity.too.large')
err.status = err.statusCode = 413
err.length = err.expected = length
err.limit = limit
cleanup()
halt(stream)
process.nextTick(function () {
var err = makeError('request entity too large', 'entity.too.large', {
expected: length,
length: length,
limit: limit,
status: 413,
statusCode: 413
})
return process.nextTick(function () {
done(err)
})
return defer
}

@@ -62,11 +196,10 @@

// developer error
var err = makeError('stream encoding should not be set',
'stream.encoding.set')
err.status = err.statusCode = 500
cleanup()
halt(stream)
process.nextTick(function () {
var err = makeError('stream encoding should not be set', 'stream.encoding.set', {
status: 500,
statusCode: 500
})
return process.nextTick(function () {
done(err)
})
return defer
}

@@ -80,8 +213,5 @@

} catch (err) {
cleanup()
halt(stream)
process.nextTick(function () {
return process.nextTick(function () {
done(err)
})
return defer
}

@@ -99,19 +229,22 @@

return defer
function done(err) {
cleanup()
// yieldable support
function defer(fn) {
done = fn
if (err) {
// halt the stream on error
halt(stream)
}
callback.apply(this, arguments)
}
function onAborted() {
var err = makeError('request aborted', 'request.aborted')
err.code = 'ECONNABORTED'
err.status = 400
err.received = received
err.length = err.expected = length
cleanup()
halt(stream)
done(err)
done(makeError('request aborted', 'request.aborted', {
code: 'ECONNABORTED',
expected: length,
length: length,
received: received,
status: 400,
statusCode: 400
}))
}

@@ -126,9 +259,8 @@

if (limit !== null && received > limit) {
var err = makeError('request entity too large', 'entity.too.large')
err.status = err.statusCode = 413
err.received = received
err.limit = limit
cleanup()
halt(stream)
done(err)
done(makeError('request entity too large', 'entity.too.large', {
limit: limit,
received: received,
status: 413,
statusCode: 413
}))
}

@@ -138,14 +270,12 @@ }

function onEnd(err) {
if (err) {
cleanup()
halt(stream)
done(err)
} else if (length !== null && received !== length) {
err = makeError('request size did not match content length',
'request.size.invalid')
err.status = err.statusCode = 400
err.received = received
err.length = err.expected = length
cleanup()
done(err)
if (err) return done(err)
if (length !== null && received !== length) {
done(makeError('request size did not match content length', 'request.size.invalid', {
expected: length,
length: length,
received: received,
status: 400,
statusCode: 400
}))
} else {

@@ -171,52 +301,7 @@ var string = decoder

function getDecoder(encoding) {
if (!encoding) return null
try {
return iconv.getCodec(encoding).decoder()
} catch (e) {
var err = makeError('specified encoding unsupported', 'encoding.unsupported')
err.status = err.statusCode = 415
err.encoding = encoding
throw err
}
}
/**
* Halt a stream.
*
* @param {Object} stream
* @api private
*/
function halt(stream) {
// unpipe everything from the stream
unpipe(stream)
// pause stream
if (typeof stream.pause === 'function') {
stream.pause()
}
}
// to create serializable errors you must re-set message so
// that it is enumerable and you must re configure the type
// property so that is writable and enumerable
function makeError(message, type) {
var error = new Error()
error.message = message
Object.defineProperty(error, 'type', {
value: type,
enumerable: true,
writable: true,
configurable: true
})
return error
}
/**
* Unpipe everything from a stream.
*
* @param {Object} stream
* @api private
* @private
*/

@@ -223,0 +308,0 @@

{
"name": "raw-body",
"description": "Get and validate the raw body of a readable stream.",
"version": "1.3.4",
"version": "2.0.0",
"author": "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)",

@@ -13,6 +13,7 @@ "contributors": [

"dependencies": {
"bytes": "1.0.0",
"bytes": "2.0.1",
"iconv-lite": "0.4.8"
},
"devDependencies": {
"bluebird": "2.9.25",
"istanbul": "0.3.9",

@@ -19,0 +20,0 @@ "mocha": "~2.2.4",

@@ -16,34 +16,7 @@ # raw-body

var getRawBody = require('raw-body')
var typer = require('media-typer')
app.use(function (req, res, next) {
getRawBody(req, {
length: req.headers['content-length'],
limit: '1mb',
encoding: typer.parse(req.headers['content-type']).parameters.charset
}, function (err, string) {
if (err)
return next(err)
req.text = string
next()
})
})
```
or in a Koa generator:
```js
app.use(function* (next) {
var string = yield getRawBody(this.req, {
length: this.length,
limit: '1mb',
encoding: this.charset
})
})
```
### getRawBody(stream, [options], [callback])
Returns a thunk for yielding with generators.
**Returns a promise if no callback specified and global `Promise` exists.**

@@ -83,2 +56,59 @@ Options:

## Examples
### Simple Express example
```js
var getRawBody = require('raw-body')
var typer = require('media-typer')
app.use(function (req, res, next) {
getRawBody(req, {
length: req.headers['content-length'],
limit: '1mb',
encoding: typer.parse(req.headers['content-type']).parameters.charset
}, function (err, string) {
if (err) return next(err)
req.text = string
next()
})
})
```
### Simple Koa example
```js
app.use(function* (next) {
var string = yield getRawBody(this.req, {
length: this.length,
limit: '1mb',
encoding: this.charset
})
})
```
### Using as a promise
To use this library as a promise, simply omit the `callback` and a promise is
returned, provided that a global `Promise` is defined.
```js
var getRawBody = require('raw-body')
var http = require('http')
var server = http.createServer(function (req, res) {
getRawBody(req)
.then(function (buf) {
res.statusCode = 200
res.end(buf.length + ' bytes submitted')
})
.catch(function (err) {
res.statusCode = 500
res.end(err.message)
})
})
server.listen(3000)
```
## License

@@ -85,0 +115,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