diff --git a/lib/read.js b/lib/read.js index 64232037..c7dceb8a 100644 --- a/lib/read.js +++ b/lib/read.js @@ -40,8 +40,20 @@ function read(req, res, next, parse, debug, options) { var opts = options || {} + var encoding = opts.encoding !== null + ? opts.encoding || 'utf-8' + : null + var verify = opts.verify + var Decryptor = opts.decryptor + try { - stream = contentstream(req, debug, opts.inflate) + if (Decryptor) { + debug('decrypt body stream') + stream = new Decryptor() + contentstream(req, debug, opts.inflate).pipe(stream) + } else { + stream = contentstream(req, debug, opts.inflate) + } length = stream.length delete stream.length } catch (err) { @@ -50,11 +62,6 @@ function read(req, res, next, parse, debug, options) { opts.length = length - var encoding = opts.encoding !== null - ? opts.encoding || 'utf-8' - : null - var verify = opts.verify - opts.encoding = verify ? null : encoding @@ -159,4 +166,4 @@ function contentstream(req, debug, inflate) { } return stream -} +} \ No newline at end of file diff --git a/lib/types/json.js b/lib/types/json.js index f6ccbc38..7a0c2e25 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -54,6 +54,7 @@ function json(options) { var strict = options.strict !== false var type = options.type || 'json' var verify = options.verify || false + var decryptor = options.decryptor || false if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -117,7 +118,8 @@ function json(options) { encoding: charset, inflate: inflate, limit: limit, - verify: verify + verify: verify, + decryptor: decryptor }) } } diff --git a/lib/types/raw.js b/lib/types/raw.js index 4f3f5447..6e9f8c83 100644 --- a/lib/types/raw.js +++ b/lib/types/raw.js @@ -36,6 +36,8 @@ function raw(options) { : options.limit var type = options.type || 'application/octet-stream' var verify = options.verify || false + var decryptor = options.decryptor || false + if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -74,7 +76,8 @@ function raw(options) { encoding: null, inflate: inflate, limit: limit, - verify: verify + verify: verify, + decryptor: decryptor }) } } diff --git a/lib/types/text.js b/lib/types/text.js index c4c725ce..0c2a2810 100644 --- a/lib/types/text.js +++ b/lib/types/text.js @@ -38,6 +38,7 @@ function text(options) { : options.limit var type = options.type || 'text/plain' var verify = options.verify || false + var decryptor = options.decryptor || false if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -79,7 +80,8 @@ function text(options) { encoding: charset, inflate: inflate, limit: limit, - verify: verify + verify: verify, + decryptor: decryptor }) } } diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index d1cd4d83..6ce586e5 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -51,6 +51,7 @@ function urlencoded(options){ : options.limit var type = options.type || 'urlencoded' var verify = options.verify || false + var decryptor = options.decryptor || false if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -106,7 +107,8 @@ function urlencoded(options){ encoding: charset, inflate: inflate, limit: limit, - verify: verify + verify: verify, + decryptor: decryptor }) } } diff --git a/package.json b/package.json index 0bf85e8a..60b11ec5 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "istanbul": "0.3.8", "methods": "~1.1.1", "mocha": "~2.2.1", - "supertest": "~0.15.0" + "supertest": "~0.15.0", + "readable-stream": "1.0.33" }, "files": [ "lib/", diff --git a/test/body-parser.js b/test/body-parser.js index 138f421a..4224f0c9 100644 --- a/test/body-parser.js +++ b/test/body-parser.js @@ -6,6 +6,10 @@ var request = require('supertest'); var bodyParser = require('..'); +var stream = require('stream'); +var util = require('util'); +var Transform = stream.Transform || require('readable-stream').Transform; + describe('bodyParser()', function(){ var server; before(function(){ @@ -138,6 +142,26 @@ describe('bodyParser()', function(){ .expect(403, 'no leading space', done) }) }) + + describe('with decryption transform stream', function(){ + it('should apply to json', function(done){ + var server = createServer({decryptor: Decryptor}) + request(server) + .post('/') + .set('Content-Type', 'application/json') + .send('eyJ1c2VyIjoidG9iaSJ9') + .expect(200, '{"user":"tobi"}', done) + }) + + it('should apply to urlencoded', function(done){ + var server = createServer({decryptor: Decryptor}) + request(server) + .post('/') + .set('Content-Type', 'application/x-www-form-urlencoded') + .send('dXNlcj10b2Jp') + .expect(200, '{"user":"tobi"}', done) + }) + }) }) function createServer(opts){ @@ -150,3 +174,29 @@ function createServer(opts){ }) }) } + +function Decryptor() { + if (!(this instanceof Decryptor)) { + return new Decryptor() + } + Transform.call(this) +} +util.inherits(Decryptor, Transform) + +Decryptor.prototype._transform = function (chunk, enc, cb) { + if (this.decrypt) { + try { + chunk = this.decrypt(chunk.toString()) + } catch (err) { + if (!err.status) err.status = 403 + throw err + } + } + this.push(chunk, 'utf-8') + cb() +}; + +Decryptor.prototype.decrypt = function(input) { + var b = new Buffer(input, "base64") + return b ? b.toString() : input +} diff --git a/test/json.js b/test/json.js index c0f2c1a8..53b95411 100644 --- a/test/json.js +++ b/test/json.js @@ -2,6 +2,9 @@ var assert = require('assert'); var http = require('http'); var request = require('supertest'); +var stream = require('stream'); +var util = require('util'); +var Transform = stream.Transform || require('readable-stream').Transform; var bodyParser = require('..');