Skip to content

Commit 49db400

Browse files
authored
Trim URLs in breadcrumbs; add maxUrlLength config opt (#906)
1 parent a264d8d commit 49db400

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

docs/config.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ Those configuration options are documented below:
205205
By default, Raven does not truncate messages. If you need to truncate
206206
characters for whatever reason, you may set this to limit the length.
207207

208+
.. describe:: maxUrlLength
209+
210+
By default, Raven will truncate URLs as they appear in breadcrumbs and other meta
211+
interfaces to 250 characters in order to minimize bytes over the wire. This does *not*
212+
affect URLs in stack traces.
213+
208214
.. describe:: autoBreadcrumbs
209215

210216
Enables/disables automatic collection of breadcrumbs. Possible values are:

src/raven.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ function Raven() {
5050
crossOrigin: 'anonymous',
5151
collectWindowErrors: true,
5252
maxMessageLength: 0,
53+
54+
// By default, truncates URL values to 250 chars
55+
maxUrlLength: 250,
5356
stackTraceLimit: 50,
5457
autoBreadcrumbs: true,
5558
sampleRate: 1
@@ -1324,9 +1327,46 @@ Raven.prototype = {
13241327
exception.value = truncate(exception.value, max);
13251328
}
13261329

1330+
var request = data.request;
1331+
if (request) {
1332+
if (request.url) {
1333+
request.url = truncate(request.url, this._globalOptions.maxUrlLength);
1334+
}
1335+
if (request.Referer) {
1336+
request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength);
1337+
}
1338+
}
1339+
1340+
if (data.breadcrumbs && data.breadcrumbs.values)
1341+
this._trimBreadcrumbs(data.breadcrumbs);
1342+
13271343
return data;
13281344
},
13291345

1346+
/**
1347+
* Truncate breadcrumb values (right now just URLs)
1348+
*/
1349+
_trimBreadcrumbs: function (breadcrumbs) {
1350+
// known breadcrumb properties with urls
1351+
// TODO: also consider arbitrary prop values that start with (https?)?://
1352+
var urlprops = {to: 1, from: 1, url: 1},
1353+
crumb,
1354+
data;
1355+
1356+
for (var i = 0; i < breadcrumbs.values.length; i++) {
1357+
crumb = breadcrumbs.values[i];
1358+
if (!crumb.hasOwnProperty('data'))
1359+
continue;
1360+
1361+
data = crumb.data;
1362+
for (var prop in urlprops) {
1363+
if (data.hasOwnProperty(prop)) {
1364+
data[prop] = truncate(data[prop], this._globalOptions.maxUrlLength);
1365+
}
1366+
}
1367+
}
1368+
},
1369+
13301370
_getHttpData: function() {
13311371
if (!this._hasNavigator && !this._hasDocument) return;
13321372
var httpData = {};

test/raven.test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ describe('globals', function() {
8888

8989
describe('trimPacket', function() {
9090
it('should work as advertised', function() {
91+
// message/excepion value (maxMessageLength)
9192
Raven._globalOptions.maxMessageLength = 3;
9293
assert.deepEqual(
9394
Raven._trimPacket({message: 'lol'}),
@@ -105,6 +106,51 @@ describe('globals', function() {
105106
Raven._trimPacket({message: 'lolol', exception: {values: [{value: 'lolol'}]}}),
106107
{message: 'lol\u2026', exception: {values: [{value: 'lol\u2026'}]}}
107108
);
109+
110+
// request URLs (maxUrlLength)
111+
Raven._globalOptions.maxUrlLength = 20;
112+
assert.deepEqual(
113+
Raven._trimPacket({request: {url: 'http://example.com/foo/bar/baz.js', Referer: 'http://example.com/f\u2026'}}),
114+
{request: {url: 'http://example.com/f\u2026', Referer: 'http://example.com/f\u2026'}}
115+
)
116+
});
117+
});
118+
119+
describe('_trimBreadcrumbs', function() {
120+
it('should work as expected', function() {
121+
Raven._globalOptions.maxUrlLength = 20;
122+
123+
var breadcrumbs = {
124+
values: [{
125+
data: {
126+
donttouch: 'this-is-not-a-url-field-and-should-not-be-touched',
127+
to: 'http://example.com/foo/bar/baz.js',
128+
from: 'http://example.com/foo/bar/baz.js'
129+
}
130+
}, {
131+
data: {
132+
donttouch: 'this-is-not-a-url-field-and-should-not-be-touched',
133+
url: 'http://example.com/foo/bar/baz.js'
134+
}
135+
}]
136+
};
137+
138+
// NOTE: _trimBreadcrumbs mutates data in-place
139+
Raven._trimBreadcrumbs(breadcrumbs);
140+
assert.deepEqual(breadcrumbs, {
141+
values: [{
142+
data: {
143+
donttouch: 'this-is-not-a-url-field-and-should-not-be-touched',
144+
to: 'http://example.com/f\u2026', // 20 chars
145+
from: 'http://example.com/f\u2026'
146+
}
147+
}, {
148+
data: {
149+
donttouch: 'this-is-not-a-url-field-and-should-not-be-touched',
150+
url: 'http://example.com/f\u2026'
151+
}
152+
}]
153+
});
108154
});
109155
});
110156

typescript/raven.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ interface RavenOptions {
5656
/** By default, Raven does not truncate messages. If you need to truncate characters for whatever reason, you may set this to limit the length. */
5757
maxMessageLength?: number;
5858

59+
/** By default, Raven will truncate URLs as they appear in breadcrumbs and other meta interfaces to 250 characters in order to minimize bytes over the wire. This does *not* affect URLs in stack traces. */
60+
maxUrlLength?: number;
61+
5962
/** Override the default HTTP data transport handler. */
6063
transport?: (options: RavenTransportOptions) => void;
6164
}

0 commit comments

Comments
 (0)