diff --git a/.travis.yml b/.travis.yml index 88913ef..bae5bb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,18 @@ language: node_js node_js: - - "0.11" + - "iojs" + - "0.12" - "0.10" - - "0.8" env: - REQUEST_VERSION=2.30.0 - - REQUEST_VERSION=2.34.0 - REQUEST_VERSION=2.40.0 - - REQUEST_VERSION=2.41.0 - - REQUEST_VERSION=2.42.0 - - REQUEST_VERSION=2.43.0 - - REQUEST_VERSION=2.44.0 - - REQUEST_VERSION=2.45.0 + - REQUEST_VERSION=2.50.0 + - REQUEST_VERSION=2.52.0 + - REQUEST_VERSION=2.53.0 + - REQUEST_VERSION=2.54.0 + - REQUEST_VERSION=2.55.0 before_script: - rm -r node_modules/request/ diff --git a/index.js b/index.js index f6db0cd..00a3006 100644 --- a/index.js +++ b/index.js @@ -1,92 +1,92 @@ -var clone = require('clone'); +var clone = require('clone') -var debugId = 0; +var debugId = 0 module.exports = exports = function(request, log) { - log = log || exports.log; + log = log || exports.log - var proto; - if (request.Request) { - proto = request.Request.prototype; - } else if (request.get && request.post) { - // The object returned by request.defaults() doesn't include the - // Request property, so do this horrible thing to get at it. Per - // Wikipedia, port 4 is unassigned. - var req = request('http://localhost:4').on('error', function() { }); - proto = req.constructor.prototype; - } else { - throw new Error( - "Pass the object returned by require('request') to this function."); - } + var proto + if (request.Request) { + proto = request.Request.prototype + } else if (request.get && request.post) { + // The object returned by request.defaults() doesn't include the + // Request property, so do this horrible thing to get at it. Per + // Wikipedia, port 4 is unassigned. + var req = request('http://localhost:4').on('error', function() { }) + proto = req.constructor.prototype + } else { + throw new Error( + "Pass the object returned by require('request') to this function.") + } - if (!proto._initBeforeDebug) { - proto._initBeforeDebug = proto.init; + if (!proto._initBeforeDebug) { + proto._initBeforeDebug = proto.init - proto.init = function() { - if (!this._debugId) { + proto.init = function() { + if (!this._debugId) { - this.on('request', function(req) { - var data = { - debugId : this._debugId, - uri : this.uri.href, - method : this.method, - headers : clone(this.headers) - }; - if (this.body) { - data.body = this.body.toString('utf8'); - } - log('request', data, this); + this.on('request', function(req) { + var data = { + debugId : this._debugId, + uri : this.uri.href, + method : this.method, + headers : clone(this.headers) + } + if (this.body) { + data.body = this.body.toString('utf8') + } + log('request', data, this) - }).on('response', function(res) { - if (this.callback) { - // callback specified, request will buffer the body for - // us, so wait until the complete event to do anything - } else { - // cannot get body since no callback specified - log('response', { - debugId : this._debugId, - headers : clone(res.headers), - statusCode : res.statusCode - }, this); - } + }).on('response', function(res) { + if (this.callback) { + // callback specified, request will buffer the body for + // us, so wait until the complete event to do anything + } else { + // cannot get body since no callback specified + log('response', { + debugId : this._debugId, + headers : clone(res.headers), + statusCode : res.statusCode + }, this) + } - }).on('complete', function(res, body) { - if (this.callback) { - log('response', { - debugId : this._debugId, - headers : clone(res.headers), - statusCode : res.statusCode, - body : res.body - }, this); - } + }).on('complete', function(res, body) { + if (this.callback) { + log('response', { + debugId : this._debugId, + headers : clone(res.headers), + statusCode : res.statusCode, + body : res.body + }, this) + } - }).on('redirect', function() { - var type = (this.response.statusCode == 401 ? 'auth' : 'redirect'); - log(type, { - debugId : this._debugId, - statusCode : this.response.statusCode, - headers : clone(this.response.headers), - uri : this.uri.href - }, this); - }); + }).on('redirect', function() { + var type = (this.response.statusCode == 401 ? 'auth' : 'redirect') + log(type, { + debugId : this._debugId, + statusCode : this.response.statusCode, + headers : clone(this.response.headers), + uri : this.uri.href + }, this) + }) - this._debugId = ++debugId; - } + this._debugId = ++debugId + } - return proto._initBeforeDebug.apply(this, arguments); - }; + return proto._initBeforeDebug.apply(this, arguments) } + } - if (!request.stopDebugging) { - request.stopDebugging = function() { - proto.init = proto._initBeforeDebug; - delete proto._initBeforeDebug; - }; + if (!request.stopDebugging) { + request.stopDebugging = function() { + proto.init = proto._initBeforeDebug + delete proto._initBeforeDebug } -}; + } +} exports.log = function(type, data, r) { - var toLog = {}; - toLog[type] = data; - console.error(toLog); -}; + var toLog = {} + toLog[type] = data + console.error(toLog) +} diff --git a/package.json b/package.json index eb2aa51..a3b221c 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,37 @@ { - "name" : "request-debug", - "author" : "James Nylen ", - "description" : "Library to assist with debugging HTTP(s) requests made by the request module.", - "version" : "0.1.1", - "repository" : { - "type" : "git", - "url" : "https://github.com/request/request-debug" - }, - "bugs" : { - "url" : "https://github.com/request/request-debug/issues" - }, - "license" : "MIT", - "keywords" : [ - "request", - "debug", - "http", - "https", - "headers" - ], - "scripts" : { - "test" : "node node_modules/.bin/mocha" - }, - "main" : "index.js", - "devDependencies" : { - "express" : "~4.8.6", - "mocha" : "~1.21.4", - "passport" : "~0.2.0", - "passport-http" : "~0.2.2", - "request" : "~2.40.0", - "should" : "~4.0.4" - }, - "dependencies" : { - "clone" : "~0.1.18" - } + "name" : "request-debug", + "author" : "James Nylen ", + "description" : "Library to assist with debugging HTTP(s) requests made by the request module.", + "version" : "0.1.1", + "repository" : { + "type" : "git", + "url" : "https://github.com/request/request-debug" + }, + "bugs" : { + "url" : "https://github.com/request/request-debug/issues" + }, + "license" : "MIT", + "keywords" : [ + "request", + "debug", + "http", + "https", + "headers" + ], + "scripts" : { + "test" : "node node_modules/.bin/mocha" + }, + "main" : "index.js", + "devDependencies" : { + "detect-engine" : "~1.0.2", + "express" : "~4.8.6", + "mocha" : "~1.21.4", + "passport" : "~0.2.0", + "passport-http" : "~0.2.2", + "request" : "~2.50.0", + "should" : "~4.0.4" + }, + "dependencies" : { + "clone" : "~0.1.18" + } } diff --git a/test/basic.js b/test/basic.js index 22b65e1..428c97a 100644 --- a/test/basic.js +++ b/test/basic.js @@ -1,520 +1,527 @@ -var lib = require('./lib'), - mocha = require('mocha'), - request = require('request'), - should = require('should'); +var engine = require('detect-engine'), + lib = require('./lib'), + mocha = require('mocha'), + request = require('request'), + should = require('should') describe('request-debug', function() { - var proto = request.Request.prototype; + var proto = request.Request.prototype - before(function() { - lib.enableDebugging(request); - lib.startServers(); + before(function() { + lib.enableDebugging(request) + lib.startServers() - request = request.defaults({ - headers : { - host : 'localhost' - }, - rejectUnauthorized : false - }); - }); + request = request.defaults({ + headers : { + host : 'localhost' + }, + rejectUnauthorized : false + }) + }) - beforeEach(function() { - lib.clearRequests(); - }); + beforeEach(function() { + lib.clearRequests() + }) - it('should capture a normal request', function(done) { - request(lib.urls.http + '/bottom', function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : 'Request OK' - } - } - ]); - done(); - }); - }); + function maybeTransferEncodingChunked(obj) { + if (engine == 'node') { + // Node sends 'Transfer-Encoding: chunked' here, io.js does not + obj['transfer-encoding'] = 'chunked' + } + return obj + } - it('should capture a request with no callback', function(done) { - var r = request(lib.urls.http + '/bottom'); - r.on('complete', function(res) { - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200 - } - } - ]); - done(); - }); - }); - - it('should capture a redirect', function(done) { - request(lib.urls.http + '/middle', function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/middle', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - redirect : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '41', - 'content-type' : 'text/plain; charset=utf-8', - date : '', - location : '/bottom', - vary : 'Accept', - 'x-powered-by' : 'Express', - }, - statusCode : 302, - uri : lib.urls.http + '/bottom' - } - }, { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - host : 'localhost:' + lib.ports.http - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : 'Request OK' - } - } - ]); - done(); - }); - }); + it('should capture a normal request', function(done) { + request(lib.urls.http + '/bottom', function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + host : 'localhost' + } + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200, + body : 'Request OK' + } + } + ]) + done() + }) + }) - it('should capture a cross-protocol redirect', function(done) { - request(lib.urls.https + '/middle/http', function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.https + '/middle/http', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - redirect : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '62', - 'content-type' : 'text/plain; charset=utf-8', - date : '', - location : lib.urls.http + '/bottom', - vary : 'Accept', - 'x-powered-by' : 'Express', - }, - statusCode : 302, - uri : lib.urls.http + '/bottom' - } - }, { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - host : 'localhost:' + lib.ports.http - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : 'Request OK' - } - } - ]); - done(); - }); - }); + it('should capture a request with no callback', function(done) { + var r = request(lib.urls.http + '/bottom') + r.on('complete', function(res) { + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + host : 'localhost' + } + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200 + } + } + ]) + done() + }) + }) - it('should capture an auth challenge', function(done) { - request(lib.urls.http + '/auth/bottom', { - auth : { - user : 'admin', - pass : 'mypass', - sendImmediately : false + it('should capture a redirect', function(done) { + request(lib.urls.http + '/middle', function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/middle', + method : 'GET', + headers : { + host : 'localhost' } - }, function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/auth/bottom', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - auth : { - debugId : lib.debugId, - headers : { - connection : '', - date : '', - 'transfer-encoding' : 'chunked', - 'www-authenticate' : 'Digest realm="Users" <+nonce,qop>', - 'x-powered-by' : 'Express', - }, - statusCode : 401, - uri : lib.urls.http + '/auth/bottom' - } - }, { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/auth/bottom', - method : 'GET', - headers : { - authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', - host : 'localhost' - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : 'Request OK' - } - } - ]); - done(); - }); - }); + } + }, { + redirect : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '41', + 'content-type' : 'text/plain; charset=utf-8', + date : '', + location : '/bottom', + vary : 'Accept', + 'x-powered-by' : 'Express', + }, + statusCode : 302, + uri : lib.urls.http + '/bottom' + } + }, { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + host : 'localhost:' + lib.ports.http + } + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200, + body : 'Request OK' + } + } + ]) + done() + }) + }) - it('should capture a complicated redirect', function(done) { - request(lib.urls.https + '/auth/top/http', { - auth : { - user : 'admin', - pass : 'mypass', - sendImmediately : false + it('should capture a cross-protocol redirect', function(done) { + request(lib.urls.https + '/middle/http', function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.https + '/middle/http', + method : 'GET', + headers : { + host : 'localhost' + } + } + }, { + redirect : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '62', + 'content-type' : 'text/plain; charset=utf-8', + date : '', + location : lib.urls.http + '/bottom', + vary : 'Accept', + 'x-powered-by' : 'Express', + }, + statusCode : 302, + uri : lib.urls.http + '/bottom' + } + }, { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + host : 'localhost:' + lib.ports.http } - }, function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.https + '/auth/top/http', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - auth : { - debugId : lib.debugId, - headers : { - connection : '', - date : '', - 'transfer-encoding' : 'chunked', - 'www-authenticate' : 'Digest realm="Users" <+nonce,qop>', - 'x-powered-by' : 'Express', - }, - statusCode : 401, - uri : lib.urls.https + '/auth/top/http' - } - }, { - request : { - debugId : lib.debugId, - uri : lib.urls.https + '/auth/top/http', - method : 'GET', - headers : { - authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', - host : 'localhost' - } - } - }, { - redirect : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '62', - 'content-type' : 'text/plain; charset=utf-8', - date : '', - location : lib.urls.http + '/middle', - vary : 'Accept', - 'x-powered-by' : 'Express', - }, - statusCode : 302, - uri : lib.urls.http + '/middle' - } - }, { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/middle', - method : 'GET', - headers : { - authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', - host : 'localhost:' + lib.ports.http - } - } - }, { - redirect : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '41', - 'content-type' : 'text/plain; charset=utf-8', - date : '', - location : '/bottom', - vary : 'Accept', - 'x-powered-by' : 'Express', - }, - statusCode : 302, - uri : lib.urls.http + '/bottom' - } - }, { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', - host : 'localhost:' + lib.ports.http - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : 'Request OK' - } - } - ]); - done(); - }); - }); + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200, + body : 'Request OK' + } + } + ]) + done() + }) + }) - it('should capture POST data and 404 responses', function(done) { - request({ - uri : lib.urls.http + '/bottom', - method : 'POST', - form : { - formKey : 'formData' + it('should capture an auth challenge', function(done) { + request(lib.urls.http + '/auth/bottom', { + auth : { + user : 'admin', + pass : 'mypass', + sendImmediately : false + } + }, function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/auth/bottom', + method : 'GET', + headers : { + host : 'localhost' } - }, function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'POST', - headers : { - host : 'localhost', - 'content-length' : 16, - 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' - }, - body : 'formKey=formData' - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '20', - 'content-type' : 'text/html; charset=utf-8', - date : '', - 'x-powered-by' : 'Express' - }, - statusCode : 404, - body : 'Cannot POST /bottom\n' - } - } - ]); - done(); - }); - }); + } + }, { + auth : { + debugId : lib.debugId, + headers : maybeTransferEncodingChunked({ + connection : '', + date : '', + 'www-authenticate' : 'Digest realm="Users" <+nonce,qop>', + 'x-powered-by' : 'Express', + }), + statusCode : 401, + uri : lib.urls.http + '/auth/bottom' + } + }, { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/auth/bottom', + method : 'GET', + headers : { + authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', + host : 'localhost' + } + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200, + body : 'Request OK' + } + } + ]) + done() + }) + }) - it('should capture JSON responses', function(done) { - request({ - uri : lib.urls.http + '/bottom', - json : true - }, function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - accept : 'application/json', - host : 'localhost' - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '15', - 'content-type' : 'application/json; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : { - key : 'value' - } - } - } - ]); - done(); - }); - }); + it('should capture a complicated redirect', function(done) { + request(lib.urls.https + '/auth/top/http', { + auth : { + user : 'admin', + pass : 'mypass', + sendImmediately : false + } + }, function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.https + '/auth/top/http', + method : 'GET', + headers : { + host : 'localhost' + } + } + }, { + auth : { + debugId : lib.debugId, + headers : maybeTransferEncodingChunked({ + connection : '', + date : '', + 'www-authenticate' : 'Digest realm="Users" <+nonce,qop>', + 'x-powered-by' : 'Express', + }), + statusCode : 401, + uri : lib.urls.https + '/auth/top/http' + } + }, { + request : { + debugId : lib.debugId, + uri : lib.urls.https + '/auth/top/http', + method : 'GET', + headers : { + authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', + host : 'localhost' + } + } + }, { + redirect : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '62', + 'content-type' : 'text/plain; charset=utf-8', + date : '', + location : lib.urls.http + '/middle', + vary : 'Accept', + 'x-powered-by' : 'Express', + }, + statusCode : 302, + uri : lib.urls.http + '/middle' + } + }, { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/middle', + method : 'GET', + headers : { + authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', + host : 'localhost:' + lib.ports.http + } + } + }, { + redirect : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '41', + 'content-type' : 'text/plain; charset=utf-8', + date : '', + location : '/bottom', + vary : 'Accept', + 'x-powered-by' : 'Express', + }, + statusCode : 302, + uri : lib.urls.http + '/bottom' + } + }, { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + authorization : 'Digest username="admin" <+realm,nonce,uri,qop,response,nc,cnonce>', + host : 'localhost:' + lib.ports.http + } + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200, + body : 'Request OK' + } + } + ]) + done() + }) + }) - it('should work with the result of request.defaults()', function(done) { - proto.should.have.property('_initBeforeDebug'); - proto.init = proto._initBeforeDebug; - delete proto._initBeforeDebug; + it('should capture POST data and 404 responses', function(done) { + request({ + uri : lib.urls.http + '/bottom', + method : 'POST', + form : { + formKey : 'formData' + } + }, function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'POST', + headers : { + host : 'localhost', + 'content-length' : 16, + 'content-type' : '' + }, + body : 'formKey=formData' + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '20', + 'content-type' : 'text/html; charset=utf-8', + date : '', + 'x-powered-by' : 'Express' + }, + statusCode : 404, + body : 'Cannot POST /bottom\n' + } + } + ]) + done() + }) + }) - request = require('request').defaults({ + it('should capture JSON responses', function(done) { + request({ + uri : lib.urls.http + '/bottom', + json : true + }, function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + accept : 'application/json', + host : 'localhost' + } + } + }, { + response : { + debugId : lib.debugId, headers : { - host : 'localhost' + connection : '', + 'content-length' : '15', + 'content-type' : 'application/json; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' }, - }); + statusCode : 200, + body : { + key : 'value' + } + } + } + ]) + done() + }) + }) + + it('should work with the result of request.defaults()', function(done) { + proto.should.have.property('_initBeforeDebug') + proto.init = proto._initBeforeDebug + delete proto._initBeforeDebug - lib.enableDebugging(request); + request = require('request').defaults({ + headers : { + host : 'localhost' + }, + }) - request(lib.urls.http + '/bottom', function(err, res, body) { - should.not.exist(err); - lib.fixVariableHeaders(); - lib.requests.should.eql([ - { - request : { - debugId : lib.debugId, - uri : lib.urls.http + '/bottom', - method : 'GET', - headers : { - host : 'localhost' - } - } - }, { - response : { - debugId : lib.debugId, - headers : { - connection : '', - 'content-length' : '10', - 'content-type' : 'text/html; charset=utf-8', - date : '', - etag : 'W/""', - 'x-powered-by' : 'Express' - }, - statusCode : 200, - body : 'Request OK' - } - } - ]); - done(); - }); - }); + lib.enableDebugging(request) + + request(lib.urls.http + '/bottom', function(err, res, body) { + should.not.exist(err) + lib.fixVariableHeaders() + lib.requests.should.eql([ + { + request : { + debugId : lib.debugId, + uri : lib.urls.http + '/bottom', + method : 'GET', + headers : { + host : 'localhost' + } + } + }, { + response : { + debugId : lib.debugId, + headers : { + connection : '', + 'content-length' : '10', + 'content-type' : 'text/html; charset=utf-8', + date : '', + etag : 'W/""', + 'x-powered-by' : 'Express' + }, + statusCode : 200, + body : 'Request OK' + } + } + ]) + done() + }) + }) - it('should not capture anything after stopDebugging()', function(done) { - request.stopDebugging(); - request(lib.urls.http + '/bottom', function(err, res, body) { - should.not.exist(err); - lib.requests.should.eql([]); - done(); - }); - }); -}); + it('should not capture anything after stopDebugging()', function(done) { + request.stopDebugging() + request(lib.urls.http + '/bottom', function(err, res, body) { + should.not.exist(err) + lib.requests.should.eql([]) + done() + }) + }) +}) diff --git a/test/lib/index.js b/test/lib/index.js index 78cbee4..5ed5ee0 100644 --- a/test/lib/index.js +++ b/test/lib/index.js @@ -1,125 +1,144 @@ -var express = require('express'), - fs = require('fs'), - http = require('http'), - https = require('https'), - mocha = require('mocha'), - passport = require('passport'), - DigestStrategy = require('passport-http').DigestStrategy, - path = require('path'), - should = require('should'), - util = require('util'); +var engine = require('detect-engine'), + express = require('express'), + fs = require('fs'), + http = require('http'), + https = require('https'), + mocha = require('mocha'), + passport = require('passport'), + DigestStrategy = require('passport-http').DigestStrategy, + path = require('path'), + should = require('should'), + util = require('util') var app, - ports = { - http : 8480, - https : 8443 - }; + ports = { + http : 8480, + https : 8443 + } -exports.ports = ports; -exports.requests = []; -exports.urls = {}; -exports.debugId = 0; +exports.ports = ports +exports.requests = [] +exports.urls = {} +exports.debugId = 0 for (var proto in ports) { - exports.urls[proto] = util.format( - '%s://localhost:%d', - proto, - ports[proto]); + exports.urls[proto] = util.format( + '%s://localhost:%d', + proto, + ports[proto]) } exports.enableDebugging = function(request) { - // enable debugging - require('../..')(request, function(type, data, r) { - var obj = {}; - obj[type] = data; - exports.requests.push(obj); - if (typeof r._initBeforeDebug != 'function') { - throw new Error('Expected a Request instance here.'); - } - }); -}; + // enable debugging + require('../..')(request, function(type, data, r) { + var obj = {} + obj[type] = data + exports.requests.push(obj) + if (typeof r._initBeforeDebug != 'function') { + throw new Error('Expected a Request instance here.') + } + }) +} exports.clearRequests = function() { - exports.requests = []; - exports.debugId++; -}; + exports.requests = [] + exports.debugId++ +} var fixHeader = { - date : function(val) { - return ''; - }, - etag : function(val) { - return val.split('"')[0] + '""'; - }, - connection : function(val) { - return val.replace(/^(close|keep-alive)$/, ''); - }, - authorization : function(val) { - var arr = val.split(', '); - if (arr.length > 1) { - val = util.format( - '%s <+%s>', - arr[0], - arr.slice(1).map(function(v) { - return v.split('=')[0] - }).join(',')); - } - return val; + date : function(val) { + return '' + }, + etag : function(val) { + return val.split('"')[0] + '""' + }, + connection : function(val) { + return val.replace(/^(close|keep-alive)$/, '') + }, + authorization : function(val) { + var arr = val.split(', ') + if (arr.length > 1) { + val = util.format( + '%s <+%s>', + arr[0], + arr.slice(1).map(function(v) { + return v.split('=')[0] + }).join(',')) + } + return val + }, + referer : function(val) { + return null + }, + 'content-type' : function(val) { + return val.replace(/^application\/x-www-form-urlencoded(; charset=utf-8)?$/, '') + }, + 'content-length' : function(val, obj) { + if (engine == 'iojs' && obj.statusCode == 401) { + // io.js sends content-length here, Node does not + return null + } else { + return val } -}; -fixHeader['www-authenticate'] = fixHeader.authorization; + } +} +fixHeader['www-authenticate'] = fixHeader.authorization exports.fixVariableHeaders = function() { - exports.requests.forEach(function(req) { - for (var type in req) { - for (var header in req[type].headers) { - if (fixHeader[header]) { - req[type].headers[header] = - fixHeader[header](req[type].headers[header]); - } - } + exports.requests.forEach(function(req) { + for (var type in req) { + for (var header in req[type].headers) { + if (fixHeader[header]) { + var fixed = fixHeader[header](req[type].headers[header], req[type]) + if (fixed === null) { + delete req[type].headers[header] + } else { + req[type].headers[header] = fixed + } } - }); -}; + } + } + }) +} exports.startServers = function() { - passport.use(new DigestStrategy( - { qop : 'auth' }, - function(user, done) { - return done(null, 'admin', 'mypass'); - } - )); + passport.use(new DigestStrategy( + { qop : 'auth' }, + function(user, done) { + return done(null, 'admin', 'mypass') + } + )) - app = express(); + app = express() - app.use(passport.initialize()); + app.use(passport.initialize()) - function handleRequest(req, res) { - if (req.params.level == 'bottom') { - if (req.header('accept') == 'application/json') { - res.json({ key : 'value' }); - } else { - res.send('Request OK'); - } - return; - } - var level = (req.params.level == 'top' ? 'middle' : 'bottom'); - if (req.params.proto && req.params.proto != req.protocol) { - res.redirect(exports.urls[req.params.proto] + '/' + level); - } else { - res.redirect('/' + level); - } + function handleRequest(req, res) { + if (req.params.level == 'bottom') { + if (req.header('accept') == 'application/json') { + res.json({ key : 'value' }) + } else { + res.send('Request OK') + } + return + } + var level = (req.params.level == 'top' ? 'middle' : 'bottom') + if (req.params.proto && req.params.proto != req.protocol) { + res.redirect(exports.urls[req.params.proto] + '/' + level) + } else { + res.redirect('/' + level) } + } - var auth = passport.authenticate('digest', { session : false }); - app.get('/auth/:level/:proto?', auth, handleRequest); + var auth = passport.authenticate('digest', { session : false }) + app.get('/auth/:level/:proto?', auth, handleRequest) - app.get('/:level/:proto?', handleRequest); + app.get('/:level/:proto?', handleRequest) - http.createServer(app).listen(ports.http); + http.createServer(app).listen(ports.http) - https.createServer({ - key : fs.readFileSync(path.join(__dirname, 'key.pem')), - cert : fs.readFileSync(path.join(__dirname, 'cert.pem')) - }, app).listen(ports.https); -}; + https.createServer({ + key : fs.readFileSync(path.join(__dirname, 'key.pem')), + cert : fs.readFileSync(path.join(__dirname, 'cert.pem')) + }, app).listen(ports.https) +}