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

Added support for brotli ('br') content-encoding #403

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ before trusting. For example, `req.body.foo.toString()` may fail in multiple
ways, for example the `foo` property may not be there or may not be a string,
and `toString` may not be a function and instead a string or other user input.

**Note** Brotli is supported only since Node.js versions v11.7.0 and v10.16.0.

[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/).

_This does not handle multipart bodies_, due to their complex and typically
Expand Down Expand Up @@ -68,8 +70,8 @@ The various errors returned by this module are described in the

Returns middleware that only parses `json` and only looks at requests where
the `Content-Type` header matches the `type` option. This parser accepts any
Unicode encoding of the body and supports automatic inflation of `gzip` and
`deflate` encodings.
Unicode encoding of the body and supports automatic inflation of `gzip`,
`br` (brotli) and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`).
Expand Down Expand Up @@ -123,7 +125,8 @@ encoding of the request. The parsing can be aborted by throwing an error.

Returns middleware that parses all bodies as a `Buffer` and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser supports automatic inflation of `gzip` and `deflate` encodings.
parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate`
encodings.

A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a `Buffer` object
Expand Down Expand Up @@ -168,7 +171,8 @@ encoding of the request. The parsing can be aborted by throwing an error.

Returns middleware that parses all bodies as a string and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser supports automatic inflation of `gzip` and `deflate` encodings.
parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate`
encodings.

A new `body` string containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a string of the
Expand Down Expand Up @@ -218,7 +222,7 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that only parses `urlencoded` bodies and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser accepts only UTF-8 encoding of the body and supports automatic
inflation of `gzip` and `deflate` encodings.
inflation of `gzip`, `br` (brotli) and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This object will contain
Expand Down
18 changes: 18 additions & 0 deletions lib/read.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ var zlib = require('zlib')

module.exports = read

/**
* @const
* whether current node version has brotli support
*/
var hasBrotliSupport = 'brotli' in process.versions

/**
* Read a request into a buffer and parse.
*
Expand Down Expand Up @@ -170,6 +176,18 @@ function contentstream (req, debug, inflate) {
stream = req
stream.length = length
break
case 'br':
if (hasBrotliSupport) {
stream = zlib.createBrotliDecompress()
debug('brotli decompress body')
req.pipe(stream)
} else {
throw createError(415, 'unsupported content encoding "' + encoding + '"', {
encoding: encoding,
type: 'encoding.unsupported'
})
}
break
default:
throw createError(415, 'unsupported content encoding "' + encoding + '"', {
encoding: encoding,
Expand Down
24 changes: 24 additions & 0 deletions test/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ var request = require('supertest')

var bodyParser = require('..')

/**
* @const
* whether current node version has brotli support
*/
var hasBrotliSupport = 'brotli' in process.versions

describe('bodyParser.json()', function () {
it('should parse JSON', function (done) {
request(createServer())
Expand Down Expand Up @@ -595,6 +601,24 @@ describe('bodyParser.json()', function () {
test.expect(200, '{"name":"论"}', done)
})

var brotlit = hasBrotliSupport ? it : it.skip
brotlit('should support brotli encoding', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'application/json')
test.write(Buffer.from('8b06807b226e616d65223a22e8aeba227d03', 'hex'))
test.expect(200, '{"name":"论"}', done)
})

var nobrotlit = hasBrotliSupport ? it.skip : it
nobrotlit('should throw 415 if there\'s no brotli support', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'application/json')
test.write(Buffer.from('8b06807b226e616d65223a22e8aeba227d03', 'hex'))
test.expect(415, 'unsupported content encoding "br"', done)
})

it('should be case-insensitive', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'GZIP')
Expand Down
24 changes: 24 additions & 0 deletions test/raw.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ var request = require('supertest')

var bodyParser = require('..')

/**
* @const
* whether current node version has brotli support
*/
var hasBrotliSupport = 'brotli' in process.versions

describe('bodyParser.raw()', function () {
before(function () {
this.server = createServer()
Expand Down Expand Up @@ -339,6 +345,24 @@ describe('bodyParser.raw()', function () {
test.expect(200, 'buf:6e616d653de8aeba', done)
})

var brotlit = hasBrotliSupport ? it : it.skip
brotlit('should support brotli encoding', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'application/octet-stream')
test.write(Buffer.from('8b03806e616d653de8aeba03', 'hex'))
test.expect(200, 'buf:6e616d653de8aeba', done)
})

var nobrotlit = hasBrotliSupport ? it.skip : it
nobrotlit('should throw 415 if there\'s no brotli support', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'application/octet-stream')
test.write(Buffer.from('8b03806e616d653de8aeba03', 'hex'))
test.expect(415, 'unsupported content encoding "br"', done)
})

it('should be case-insensitive', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'GZIP')
Expand Down
24 changes: 24 additions & 0 deletions test/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ var request = require('supertest')

var bodyParser = require('..')

/**
* @const
* whether current node version has brotli support
*/
var hasBrotliSupport = 'brotli' in process.versions

describe('bodyParser.text()', function () {
before(function () {
this.server = createServer()
Expand Down Expand Up @@ -407,6 +413,24 @@ describe('bodyParser.text()', function () {
test.expect(200, '"name is 论"', done)
})

var brotlit = hasBrotliSupport ? it : it.skip
brotlit('should support brotli encoding', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'text/plain')
test.write(Buffer.from('0b05806e616d6520697320e8aeba03', 'hex'))
test.expect(200, '"name is 论"', done)
})

var nobrotlit = hasBrotliSupport ? it.skip : it
nobrotlit('should throw 415 if there\'s no brotli support', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'text/plain')
test.write(Buffer.from('0b05806e616d6520697320e8aeba03', 'hex'))
test.expect(415, 'unsupported content encoding "br"', done)
})

it('should be case-insensitive', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'GZIP')
Expand Down
24 changes: 24 additions & 0 deletions test/urlencoded.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ var request = require('supertest')

var bodyParser = require('..')

/**
* @const
* whether current node version has brotli support
*/
var hasBrotliSupport = 'brotli' in process.versions

describe('bodyParser.urlencoded()', function () {
before(function () {
this.server = createServer()
Expand Down Expand Up @@ -681,6 +687,24 @@ describe('bodyParser.urlencoded()', function () {
test.expect(200, '{"name":"论"}', done)
})

var brotlit = hasBrotliSupport ? it : it.skip
brotlit('should support brotli encoding', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'application/x-www-form-urlencoded')
test.write(Buffer.from('8b03806e616d653de8aeba03', 'hex'))
test.expect(200, '{"name":"论"}', done)
})

var nobrotlit = hasBrotliSupport ? it.skip : it
nobrotlit('should throw 415 if there\'s no brotli support', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'br')
test.set('Content-Type', 'application/x-www-form-urlencoded')
test.write(Buffer.from('789ccb4bcc4db57db16e17001068042f', 'hex'))
test.expect(415, 'unsupported content encoding "br"', done)
})

it('should be case-insensitive', function (done) {
var test = request(this.server).post('/')
test.set('Content-Encoding', 'GZIP')
Expand Down