Skip to content
Merged
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
29 changes: 29 additions & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,41 @@ Those configuration options are documented below:
sentry_key
Your public client key (DSN).

options
Include all top-level options described.

onSuccess
Callback to be invoked upon a successful request.

onError
Callback to be invoked upon a failed request.

.. describe:: headers

Pass custom headers to server requests for ``fetch`` or ``XMLHttpRequest``.

.. code-block:: javascript

{
headers: {
'CSRF-TOKEN': '12345'
}
}

Headers value can be in form of a function, to compute value in time of a request:

.. code-block:: javascript

{
headers: {
'CSRF-TOKEN': function() {
// custom logic that will be computed on every request
return new Date();
}
}
}


.. describe:: allowDuplicates

By default, Raven.js attempts to suppress duplicate captured errors and messages that occur back-to-back. Such events are often triggered by rogue code (e.g. from a `setInterval` callback in a browser extension), are not actionable, and eat up your event quota.
Expand Down
40 changes: 36 additions & 4 deletions src/raven.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ function Raven() {
ignoreUrls: [],
whitelistUrls: [],
includePaths: [],
headers: null,
collectWindowErrors: true,
maxMessageLength: 0,

Expand Down Expand Up @@ -1897,12 +1898,23 @@ Raven.prototype = {
// Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests
var url = opts.url + '?' + urlencode(opts.auth);

var evaluatedHeaders = null;
if (opts.options.headers) {
evaluatedHeaders = this._evaluateHeaders(opts.options.headers);
}

if (supportsFetch()) {
var fetchOptions = {
method: 'POST',
body: stringify(opts.data)
};

if (evaluatedHeaders) {
fetchOptions.headers = evaluatedHeaders;
}

return _window
.fetch(url, {
method: 'POST',
body: stringify(opts.data)
})
.fetch(url, fetchOptions)
.then(function(response) {
if (response.ok) {
opts.onSuccess && opts.onSuccess();
Expand Down Expand Up @@ -1960,9 +1972,29 @@ Raven.prototype = {
}

request.open('POST', url);

if (evaluatedHeaders) {
each(evaluatedHeaders, function(key, value) {
request.setRequestHeader(key, value);
});
}

request.send(stringify(opts.data));
},

_evaluateHeaders: function(headers) {
var evaluatedHeaders = {};

for (var key in headers) {
if (headers.hasOwnProperty(key)) {
var value = headers[key];
evaluatedHeaders[key] = typeof value === 'function' ? value() : value;
}
}

return evaluatedHeaders;
},

_logDebug: function(level) {
if (this._originalConsoleMethods[level] && this.debug) {
// In IE<10 console methods do not have their own 'apply' method
Expand Down
42 changes: 42 additions & 0 deletions test/raven.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,48 @@ describe('globals', function() {
});
});

it('should apply globalOptions.headers if specified', function() {
this.sinon.stub(Raven, 'isSetup').returns(true);
this.sinon.stub(window, 'fetch').resolves(true);

Raven._globalProject = '2';
Raven._globalOptions = {
logger: 'javascript',
maxMessageLength: 100,
headers: {
'custom-header': 'value'
}
};

Raven._send({message: 'bar'});

assert.deepEqual(window.fetch.lastCall.args[1].headers, {
'custom-header': 'value'
});
});

it('should apply globalOptions.headers with function value if specified', function() {
this.sinon.stub(Raven, 'isSetup').returns(true);
this.sinon.stub(window, 'fetch').resolves(true);

Raven._globalProject = '2';
Raven._globalOptions = {
logger: 'javascript',
maxMessageLength: 100,
headers: {
'custom-header': function() {
return 'computed-header-value';
}
}
};

Raven._send({message: 'bar'});

assert.deepEqual(window.fetch.lastCall.args[1].headers, {
'custom-header': 'computed-header-value'
});
});

it('should check `Raven.isSetup`', function() {
this.sinon.stub(Raven, 'isSetup').returns(false);
this.sinon.stub(Raven, '_makeRequest');
Expand Down
5 changes: 5 additions & 0 deletions typescript/raven.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ declare module Raven {
/** Override the default HTTP data transport handler. */
transport?: (options: RavenTransportOptions) => void;

/** Append headers to the fetch or XMLHttpRequest request. Should be in a form of hash, were value can be string or function */
headers?: {
[key: string]: (string | Function);
};

/** Allow use of private/secretKey. */
allowSecretKey?: boolean;

Expand Down