getsentry / examples

Collection of all different kinds of Sentry SDKs and integrations
MIT License
120 stars 102 forks source link

Cannot access 'url' before initialization #131

Closed mikey-mo closed 1 year ago

mikey-mo commented 2 years ago

Environment

How do you use Sentry? Sentry SaaS (sentry.io)

Which SDK and version? @sentry/nextjs 6.12.0

Steps to Reproduce

  1. Pull example NextJS project
  2. Install dependencies
  3. Open Console
  4. See 400 Response from <url>/api/tunnel

Expected Result

API should consume request without error

Actual Result

API errors because of a constant, url.

/pages/api/tunnel

import * as url from 'url';

---

const url = `https://${sentryHost}/api/${projectId}/envelope/`;

Which results in error log:

ReferenceError: Cannot access 'url' before initialization
callum-gander commented 2 years ago

Also getting this error, did you solve it? Or does anyone from Sentry have any suggestions?

myxoh commented 2 years ago

I wouldn't trust this sample code - they are using a legacy API anyway for url.parse anyway

I did the following instead:

    const dsnUrl = new URL(header.dsn);
    const host = dsnUrl.host;
    const path = dsnUrl.pathname

and remove the import for url

Some other changes were: in my case the projecrUrl had / at the beginning of the path (as that's how pathname works) - this also happened on their sample code so I changed to:

    const dsnUrl = new URL(header.dsn);
    const host = dsnUrl.host;
    const path = dsnUrl.pathname.slice(1, -1);

Finally in my case I had to add an await on the .json() call at the end to avoid the request hanging on the tunnel (json() is a promise)

    const response = await fetch(errorUrl, {
      method: "POST",
      body: envelope,
    });
    const jsonResponse = await response.json();
    return jsonResponse;
callum-gander commented 2 years ago

@myxoh thanks, that sorted it out for me! For anyone else finding this later, what worked for me was


async function handler(req, res) {
    try {
        const envelope = req.body;
        const pieces = envelope.split("\n");
        const header = JSON.parse(pieces[0]);
        const dsnUrl = new URL(header.dsn);
        const host = dsnUrl.host;
        const path = dsnUrl.pathname.slice(1, -1);

        const projectId = path;

        const url = `https://${host}/api/${projectId}/envelope/`;

        const response = await fetch(url, {
            method: "POST",
            body: envelope,
        });
        const jsonResponse = await response.json();
        return jsonResponse;
    } catch (e) {
        captureException(e);
        return res.status(400).json({ status: e });
    }
}
AbhiPrasad commented 1 year ago

If you upgrade to Next.js SDK 7.26.0 or higher (we recommend using latest) you can use the tunnelRoute option to automatically set up a tunnel. We recommend you use this option for tunneling instead of setting up your own.

See the docs: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-tunneling-to-avoid-ad-blockers

// next.config.js
const nextConfig = {
  sentry: {
    tunnelRoute: "/monitoring-tunnel",
  },
};

Closing this issue for repo cleanup - please let us know if this still applies. Thanks!