I set up Sentry cloud in our React application but it's blocked by Ad Blockers (when turning the Ad blocker off, it works).
Is there someone who successfully set up a tunnel in a React application?
- I played around with CORS but it didn't work
- Playing around with the tunnel property in Sentry.init from the nextjs example in https://github.com/getsentry/examples/blob/master/tunneling/nextjs/pages/api/tunnel.js is throwing a
/tunnel 404 (Not Found)console error in react app although I added a route to this path into my App which contains thehandlefunction from nextjs example.
...
Sentry.init({
dsn: 'https://[email protected]/mine',
integrations: [new BrowserTracing()],
environment,
tunnel: '/tunnel',
tracesSampleRate,
});
...
where I tried it directly via <Route path='/tunnel' component={(req, res) => handle(req, res)} /> and also by using a component <Route path='/tunnel' component={Tunnel} /> with
function Tunnel(props) {
let location = useLocation();
useEffect(() => {
if(location.pathname === '/tunnel') {
handle(props.req, props.res);
}
}, [location.pathname]);
return null;
}
- I even tried Webpack Plugin
plugins: [
new SentryWebpackPlugin({
include: '.',
ignore: ['node_modules'],
org: 'my_org',
project: 'app',
authToken:
'myToken',
}),
],
but it also is being getting blocked
--- Update --- At least for local development and testing, it's possible to adjust the webpack config.
const bodyParser = require('body-parser')
const sentryHost = '@o<orgId>.ingest.sentry.io';
// Set knownProjectIds to an array with your Sentry project IDs which you
// want to accept through this proxy.
const knownProjectIds = ['12345'];
app.use(bodyParser.text());
app?.post('/tunnel', async (req, res) => {
try {
const envelope = req.body;
const pieces = envelope.split('\n');
const header = JSON.parse(pieces[0]);
// DSNs are of the form `https://<key>@o<orgId>.ingest.sentry.io/<projectId>`
const { host, pathname } = new URL(header.dsn);
// Remove leading slash
const projectId = pathname.substring(1);
if (host !== sentryHost) {
throw new Error(`invalid host: ${host}`);
}
if (!knownProjectIds.includes(projectId)) {
throw new Error(`invalid project id: $. {projectId}`);
}
const sentryIngestURL = `https://${sentryHost}/api/${projectId}/envelope/`;
const sentryResponse = await fetch(sentryIngestURL, {
method: 'POST',
body: envelope,
});
sentryResponse.headers.forEach(([key, value]) => res.setHeader(key, value));
res.status(sentryResponse.status).send(sentryResponse.body);
} catch (e) {
captureException(e);
return res.status(400).json({ status: 'invalid request' });
}
res.send("POST res sent from webpack dev server")
})
but only for local testing. In production, I guess we would use a proxy.
Dealing with Ad-Blockers
When you are using sentry CDN, ad-blocking or script-blocking extensions may prevent sentry SDK from being fetched and initialized properly. Because of this, any call to the SDKs API will fail and may cause your application to behave unexpectedly.
Additionally, even when the SDK is downloaded and initialized correctly, Sentry endpoints that need to receive captured data may be blocked as well. This prevents any error reports, session health, or performance data from being delivered, making it effectively unavailable in sentry.io.
Furthermore, some browsers, like Brave, have built-in ad-blockers that may block requests sent to our endpoint. Even if users deactivate your domain from blocking, Brave might continue to block requests made by service workers.
Using the
tunnelOptionA tunnel is an HTTP endpoint that acts as a proxy between Sentry and your application. Because you control this server, there is no risk of any requests sent to it being blocked. When the endpoint lives under the same origin (although it does not have to in order for the tunnel to work), the browser will not treat any requests to the endpoint as a third-party request. As a result, these requests will have different security measures applied which, by default, don't trigger ad-blockers. A quick summary of the flow can be found below.
You can setup a
tunnelroute using a backend node server or choose your preferred backend language.NodeJS - server.js
You can find the full NodeJS server code here
After setup, the backend server makes some changes on the
front-endreact app.You need to setup a proxy on the
frontendapp. If you're usingCRAyou just follow these stpes.For more details https://create-react-app.dev/docs/proxying-api-requests-in-development/
First, install
http-proxy-middlewareusing npm or Yarn:Next, create
src/setupProxy.jsand place the following contents in it:You can now register proxies as you wish! Here's an example using the above
http-proxy-middleware:After done with the
proxysetup make some changes where you initialize thesentryconfigurationOnce finished with the setup just restart your
reactapp. You will be able to catch errors by tunneling. Go to thesentrydashboard and check it.