|  | 
|  | 1 | +import type * as S from '@sentry/node'; | 
|  | 2 | +const Sentry = require('@sentry/node') as typeof S; | 
|  | 3 | + | 
|  | 4 | +// We wrap console.warn to find out if a warning is incorrectly logged | 
|  | 5 | +console.warn = new Proxy(console.warn, { | 
|  | 6 | +  apply: function (target, thisArg, argumentsList) { | 
|  | 7 | +    const msg = argumentsList[0]; | 
|  | 8 | +    if (typeof msg === 'string' && msg.startsWith('[Sentry]')) { | 
|  | 9 | +      console.error(`Sentry warning was triggered: ${msg}`); | 
|  | 10 | +      process.exit(1); | 
|  | 11 | +    } | 
|  | 12 | + | 
|  | 13 | +    return target.apply(thisArg, argumentsList); | 
|  | 14 | +  }, | 
|  | 15 | +}); | 
|  | 16 | + | 
|  | 17 | +Sentry.init({ | 
|  | 18 | +  environment: 'qa', // dynamic sampling bias to keep transactions | 
|  | 19 | +  dsn: process.env.E2E_TEST_DSN, | 
|  | 20 | +  integrations: [], | 
|  | 21 | +  tracesSampleRate: 1, | 
|  | 22 | +  tunnel: 'http://localhost:3031/', // proxy server | 
|  | 23 | +  tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], | 
|  | 24 | +}); | 
|  | 25 | + | 
|  | 26 | +import type * as H from 'http'; | 
|  | 27 | +import type * as F from 'fastify'; | 
|  | 28 | + | 
|  | 29 | +// Make sure fastify is imported after Sentry is initialized | 
|  | 30 | +const { fastify } = require('fastify') as typeof F; | 
|  | 31 | +const http = require('http') as typeof H; | 
|  | 32 | + | 
|  | 33 | +const app = fastify(); | 
|  | 34 | +const port = 3030; | 
|  | 35 | +const port2 = 3040; | 
|  | 36 | + | 
|  | 37 | +Sentry.setupFastifyErrorHandler(app); | 
|  | 38 | + | 
|  | 39 | +app.get('/test-success', function (_req, res) { | 
|  | 40 | +  res.send({ version: 'v1' }); | 
|  | 41 | +}); | 
|  | 42 | + | 
|  | 43 | +app.get<{ Params: { param: string } }>('/test-param/:param', function (req, res) { | 
|  | 44 | +  res.send({ paramWas: req.params.param }); | 
|  | 45 | +}); | 
|  | 46 | + | 
|  | 47 | +app.get<{ Params: { id: string } }>('/test-inbound-headers/:id', function (req, res) { | 
|  | 48 | +  const headers = req.headers; | 
|  | 49 | + | 
|  | 50 | +  res.send({ headers, id: req.params.id }); | 
|  | 51 | +}); | 
|  | 52 | + | 
|  | 53 | +app.get<{ Params: { id: string } }>('/test-outgoing-http/:id', async function (req, res) { | 
|  | 54 | +  const id = req.params.id; | 
|  | 55 | +  const data = await makeHttpRequest(`http://localhost:3030/test-inbound-headers/${id}`); | 
|  | 56 | + | 
|  | 57 | +  res.send(data); | 
|  | 58 | +}); | 
|  | 59 | + | 
|  | 60 | +app.get<{ Params: { id: string } }>('/test-outgoing-fetch/:id', async function (req, res) { | 
|  | 61 | +  const id = req.params.id; | 
|  | 62 | +  const response = await fetch(`http://localhost:3030/test-inbound-headers/${id}`); | 
|  | 63 | +  const data = await response.json(); | 
|  | 64 | + | 
|  | 65 | +  res.send(data); | 
|  | 66 | +}); | 
|  | 67 | + | 
|  | 68 | +app.get('/test-transaction', async function (req, res) { | 
|  | 69 | +  Sentry.startSpan({ name: 'test-span' }, () => { | 
|  | 70 | +    Sentry.startSpan({ name: 'child-span' }, () => {}); | 
|  | 71 | +  }); | 
|  | 72 | + | 
|  | 73 | +  res.send({}); | 
|  | 74 | +}); | 
|  | 75 | + | 
|  | 76 | +app.get('/test-error', async function (req, res) { | 
|  | 77 | +  const exceptionId = Sentry.captureException(new Error('This is an error')); | 
|  | 78 | + | 
|  | 79 | +  await Sentry.flush(2000); | 
|  | 80 | + | 
|  | 81 | +  res.send({ exceptionId }); | 
|  | 82 | +}); | 
|  | 83 | + | 
|  | 84 | +app.get<{ Params: { id: string } }>('/test-exception/:id', async function (req, res) { | 
|  | 85 | +  throw new Error(`This is an exception with id ${req.params.id}`); | 
|  | 86 | +}); | 
|  | 87 | + | 
|  | 88 | +app.get('/test-outgoing-fetch-external-allowed', async function (req, res) { | 
|  | 89 | +  const fetchResponse = await fetch(`http://localhost:${port2}/external-allowed`); | 
|  | 90 | +  const data = await fetchResponse.json(); | 
|  | 91 | + | 
|  | 92 | +  res.send(data); | 
|  | 93 | +}); | 
|  | 94 | + | 
|  | 95 | +app.get('/test-outgoing-fetch-external-disallowed', async function (req, res) { | 
|  | 96 | +  const fetchResponse = await fetch(`http://localhost:${port2}/external-disallowed`); | 
|  | 97 | +  const data = await fetchResponse.json(); | 
|  | 98 | + | 
|  | 99 | +  res.send(data); | 
|  | 100 | +}); | 
|  | 101 | + | 
|  | 102 | +app.get('/test-outgoing-http-external-allowed', async function (req, res) { | 
|  | 103 | +  const data = await makeHttpRequest(`http://localhost:${port2}/external-allowed`); | 
|  | 104 | +  res.send(data); | 
|  | 105 | +}); | 
|  | 106 | + | 
|  | 107 | +app.get('/test-outgoing-http-external-disallowed', async function (req, res) { | 
|  | 108 | +  const data = await makeHttpRequest(`http://localhost:${port2}/external-disallowed`); | 
|  | 109 | +  res.send(data); | 
|  | 110 | +}); | 
|  | 111 | + | 
|  | 112 | +app.listen({ port: port }); | 
|  | 113 | + | 
|  | 114 | +// A second app so we can test header propagation between external URLs | 
|  | 115 | +const app2 = fastify(); | 
|  | 116 | +app2.get('/external-allowed', function (req, res) { | 
|  | 117 | +  const headers = req.headers; | 
|  | 118 | + | 
|  | 119 | +  res.send({ headers, route: '/external-allowed' }); | 
|  | 120 | +}); | 
|  | 121 | + | 
|  | 122 | +app2.get('/external-disallowed', function (req, res) { | 
|  | 123 | +  const headers = req.headers; | 
|  | 124 | + | 
|  | 125 | +  res.send({ headers, route: '/external-disallowed' }); | 
|  | 126 | +}); | 
|  | 127 | + | 
|  | 128 | +app2.listen({ port: port2 }); | 
|  | 129 | + | 
|  | 130 | +function makeHttpRequest(url: string) { | 
|  | 131 | +  return new Promise(resolve => { | 
|  | 132 | +    const data: any[] = []; | 
|  | 133 | + | 
|  | 134 | +    http | 
|  | 135 | +      .request(url, httpRes => { | 
|  | 136 | +        httpRes.on('data', chunk => { | 
|  | 137 | +          data.push(chunk); | 
|  | 138 | +        }); | 
|  | 139 | +        httpRes.on('error', error => { | 
|  | 140 | +          resolve({ error: error.message, url }); | 
|  | 141 | +        }); | 
|  | 142 | +        httpRes.on('end', () => { | 
|  | 143 | +          try { | 
|  | 144 | +            const json = JSON.parse(Buffer.concat(data).toString()); | 
|  | 145 | +            resolve(json); | 
|  | 146 | +          } catch { | 
|  | 147 | +            resolve({ data: Buffer.concat(data).toString(), url }); | 
|  | 148 | +          } | 
|  | 149 | +        }); | 
|  | 150 | +      }) | 
|  | 151 | +      .end(); | 
|  | 152 | +  }); | 
|  | 153 | +} | 
0 commit comments