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
16 changes: 8 additions & 8 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init'),
gzip: true,
limit: '25 KB',
limit: '25.5 KB',
},
{
name: '@sentry/browser - with treeshaking flags',
Expand Down Expand Up @@ -148,7 +148,7 @@ module.exports = [
import: createImport('init', 'ErrorBoundary', 'reactRouterV6BrowserTracingIntegration'),
ignore: ['react/jsx-runtime'],
gzip: true,
limit: '44 KB',
limit: '44.5 KB',
},
// Vue SDK (ESM)
{
Expand All @@ -171,20 +171,20 @@ module.exports = [
path: 'packages/svelte/build/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '25 KB',
limit: '25.5 KB',
},
// Browser CDN bundles
{
name: 'CDN Bundle',
path: createCDNPath('bundle.min.js'),
gzip: true,
limit: '27.5 KB',
limit: '28 KB',
},
{
name: 'CDN Bundle (incl. Tracing)',
path: createCDNPath('bundle.tracing.min.js'),
gzip: true,
limit: '42.5 KB',
limit: '43 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Replay)',
Expand Down Expand Up @@ -234,7 +234,7 @@ module.exports = [
import: createImport('init'),
ignore: ['next/router', 'next/constants'],
gzip: true,
limit: '46.5 KB',
limit: '47 KB',
},
// SvelteKit SDK (ESM)
{
Expand All @@ -243,7 +243,7 @@ module.exports = [
import: createImport('init'),
ignore: ['$app/stores'],
gzip: true,
limit: '42.5 KB',
limit: '43 KB',
},
// Node-Core SDK (ESM)
{
Expand All @@ -261,7 +261,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '162.5 KB',
limit: '163 KB',
},
{
name: '@sentry/node - without tracing',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
enhanceFetchErrorMessages: false,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Based on possible TypeError exceptions from https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch

// Network error (e.g. ad-blocked, offline, page does not exist, ...)
window.networkError = () => {
fetch('http://sentry-test-external.io/does-not-exist');
};

window.networkErrorSubdomain = () => {
fetch('http://subdomain.sentry-test-external.io/does-not-exist');
};

window.networkErrorWithPort = () => {
fetch('http://sentry-test-external.io:3000/does-not-exist');
};

// Invalid header also produces TypeError
window.invalidHeaderName = () => {
fetch('http://sentry-test-external.io/invalid-header-name', { headers: { 'C ontent-Type': 'text/xml' } });
};

// Invalid header value also produces TypeError
window.invalidHeaderValue = () => {
fetch('http://sentry-test-external.io/invalid-header-value', { headers: ['Content-Type', 'text/html', 'extra'] });
};

// Invalid URL scheme
window.invalidUrlScheme = () => {
fetch('blub://sentry-test-external.io/invalid-scheme');
};

// URL includes credentials
window.credentialsInUrl = () => {
fetch('https://user:[email protected]/credentials-in-url');
};

// Invalid mode
window.invalidMode = () => {
fetch('https://sentry-test-external.io/invalid-mode', { mode: 'navigate' });
};

// Invalid request method
window.invalidMethod = () => {
fetch('http://sentry-test-external.io/invalid-method', { method: 'CONNECT' });
};

// No-cors mode with cors-required method
window.noCorsMethod = () => {
fetch('http://sentry-test-external.io/no-cors-method', { mode: 'no-cors', method: 'PUT' });
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { expect } from '@playwright/test';
import { sentryTest } from '../../../utils/fixtures';
import { envelopeRequestParser, waitForErrorRequest } from '../../../utils/helpers';

sentryTest(
'enhanceFetchErrorMessages: false: enhances error for Sentry while preserving original',
async ({ getLocalTestUrl, page, browserName }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const reqPromise = waitForErrorRequest(page);
const pageErrorPromise = new Promise<string>(resolve => {
page.on('pageerror', error => {
resolve(error.message);
});
});

await page.goto(url);
await page.evaluate('networkError()');

const [req, pageErrorMessage] = await Promise.all([reqPromise, pageErrorPromise]);
const eventData = envelopeRequestParser(req);
const originalErrorMap: Record<string, string> = {
chromium: 'Failed to fetch',
webkit: 'Load failed',
firefox: 'NetworkError when attempting to fetch resource.',
};

const originalError = originalErrorMap[browserName];

expect(pageErrorMessage).toContain(originalError);
expect(pageErrorMessage).not.toContain('sentry-test-external.io');

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
type: 'TypeError',
value: originalError,
mechanism: {
handled: false,
type: 'auto.browser.global_handlers.onunhandledrejection',
},
});
},
);

sentryTest(
'enhanceFetchErrorMessages: false: enhances subdomain errors',
async ({ getLocalTestUrl, page, browserName }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const reqPromise = waitForErrorRequest(page);
const pageErrorPromise = new Promise<string>(resolve => page.on('pageerror', error => resolve(error.message)));

await page.goto(url);
await page.evaluate('networkErrorSubdomain()');

const [req, pageErrorMessage] = await Promise.all([reqPromise, pageErrorPromise]);
const eventData = envelopeRequestParser(req);

const originalErrorMap: Record<string, string> = {
chromium: 'Failed to fetch',
webkit: 'Load failed',
firefox: 'NetworkError when attempting to fetch resource.',
};

const originalError = originalErrorMap[browserName];

expect(pageErrorMessage).toContain(originalError);
expect(pageErrorMessage).not.toContain('subdomain.sentry-test-external.io');
expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
type: 'TypeError',
value: originalError,
mechanism: {
handled: false,
type: 'auto.browser.global_handlers.onunhandledrejection',
},
});
},
);

sentryTest(
'enhanceFetchErrorMessages: false: includes port in hostname',
async ({ getLocalTestUrl, page, browserName }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const reqPromise = waitForErrorRequest(page);

const pageErrorPromise = new Promise<string>(resolve => page.on('pageerror', error => resolve(error.message)));

await page.goto(url);
await page.evaluate('networkErrorWithPort()');

const [req, pageErrorMessage] = await Promise.all([reqPromise, pageErrorPromise]);
const eventData = envelopeRequestParser(req);

const originalErrorMap: Record<string, string> = {
chromium: 'Failed to fetch',
webkit: 'Load failed',
firefox: 'NetworkError when attempting to fetch resource.',
};

const originalError = originalErrorMap[browserName];

expect(pageErrorMessage).toContain(originalError);
expect(pageErrorMessage).not.toContain('sentry-test-external.io:3000');
expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
type: 'TypeError',
value: originalError,
mechanism: {
handled: false,
type: 'auto.browser.global_handlers.onunhandledrejection',
},
});
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
enhanceFetchErrorMessages: 'report-only',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Based on possible TypeError exceptions from https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch

// Network error (e.g. ad-blocked, offline, page does not exist, ...)
window.networkError = () => {
fetch('http://sentry-test-external.io/does-not-exist');
};

window.networkErrorSubdomain = () => {
fetch('http://subdomain.sentry-test-external.io/does-not-exist');
};

window.networkErrorWithPort = () => {
fetch('http://sentry-test-external.io:3000/does-not-exist');
};

// Invalid header also produces TypeError
window.invalidHeaderName = () => {
fetch('http://sentry-test-external.io/invalid-header-name', { headers: { 'C ontent-Type': 'text/xml' } });
};

// Invalid header value also produces TypeError
window.invalidHeaderValue = () => {
fetch('http://sentry-test-external.io/invalid-header-value', { headers: ['Content-Type', 'text/html', 'extra'] });
};

// Invalid URL scheme
window.invalidUrlScheme = () => {
fetch('blub://sentry-test-external.io/invalid-scheme');
};

// URL includes credentials
window.credentialsInUrl = () => {
fetch('https://user:[email protected]/credentials-in-url');
};

// Invalid mode
window.invalidMode = () => {
fetch('https://sentry-test-external.io/invalid-mode', { mode: 'navigate' });
};

// Invalid request method
window.invalidMethod = () => {
fetch('http://sentry-test-external.io/invalid-method', { method: 'CONNECT' });
};

// No-cors mode with cors-required method
window.noCorsMethod = () => {
fetch('http://sentry-test-external.io/no-cors-method', { mode: 'no-cors', method: 'PUT' });
};
Loading
Loading