'use strict'; var util = require('util'); var utils = require('../utils'); module.exports = function(Raven, http, originals) { var OrigClientRequest = http.ClientRequest; var ClientRequest = function(options, cb) { // Note: this won't capture a breadcrumb if a response never comes // It would be useful to know if that was the case, though, so // todo: revisit to see if we can capture sth indicating response never came // possibility: capture one breadcrumb for "req sent" and one for "res recvd" // seems excessive but solves the problem and *is* strictly more information // could be useful for weird response sequencing bug scenarios OrigClientRequest.call(this, options, cb); // We could just always reconstruct this from this.agent, this._headers, this.path, etc // but certain other http-instrumenting libraries (like nock, which we use for tests) fail to // maintain the guarantee that after calling OrigClientRequest, those fields will be populated if (typeof options === 'string') { this.__ravenBreadcrumbUrl = options; } else { this.__ravenBreadcrumbUrl = (options.protocol || '') + '//' + (options.hostname || options.host || '') + (options.path || '/'); } }; util.inherits(ClientRequest, OrigClientRequest); utils.fill(ClientRequest.prototype, 'emit', function(origEmit) { return function(evt, maybeResp) { if (evt === 'response' && this.__ravenBreadcrumbUrl) { if (!Raven.dsn || this.__ravenBreadcrumbUrl.indexOf(Raven.dsn.host) === -1) { Raven.captureBreadcrumb({ type: 'http', category: 'http', data: { method: this.method, url: this.__ravenBreadcrumbUrl, status_code: maybeResp.statusCode } }); } } return origEmit.apply(this, arguments); }; }); utils.fill( http, 'ClientRequest', function() { return ClientRequest; }, originals ); // http.request orig refs module-internal ClientRequest, not exported one, so // it still points at orig ClientRequest after our monkeypatch; these reimpls // just get that reference updated to use our new ClientRequest utils.fill( http, 'request', function() { return function(options, cb) { return new http.ClientRequest(options, cb); }; }, originals ); utils.fill( http, 'get', function() { return function(options, cb) { var req = http.request(options, cb); req.end(); return req; }; }, originals ); return http; };