fetch.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. Object.defineProperty(exports, '__esModule', { value: true });
  2. const object = require('../object.js');
  3. const supports = require('../supports.js');
  4. const worldwide = require('../worldwide.js');
  5. const _handlers = require('./_handlers.js');
  6. /**
  7. * Add an instrumentation handler for when a fetch request happens.
  8. * The handler function is called once when the request starts and once when it ends,
  9. * which can be identified by checking if it has an `endTimestamp`.
  10. *
  11. * Use at your own risk, this might break without changelog notice, only used internally.
  12. * @hidden
  13. */
  14. function addFetchInstrumentationHandler(handler) {
  15. const type = 'fetch';
  16. _handlers.addHandler(type, handler);
  17. _handlers.maybeInstrument(type, instrumentFetch);
  18. }
  19. function instrumentFetch() {
  20. if (!supports.supportsNativeFetch()) {
  21. return;
  22. }
  23. object.fill(worldwide.GLOBAL_OBJ, 'fetch', function (originalFetch) {
  24. return function (...args) {
  25. const { method, url } = parseFetchArgs(args);
  26. const handlerData = {
  27. args,
  28. fetchData: {
  29. method,
  30. url,
  31. },
  32. startTimestamp: Date.now(),
  33. };
  34. _handlers.triggerHandlers('fetch', {
  35. ...handlerData,
  36. });
  37. // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
  38. return originalFetch.apply(worldwide.GLOBAL_OBJ, args).then(
  39. (response) => {
  40. const finishedHandlerData = {
  41. ...handlerData,
  42. endTimestamp: Date.now(),
  43. response,
  44. };
  45. _handlers.triggerHandlers('fetch', finishedHandlerData);
  46. return response;
  47. },
  48. (error) => {
  49. const erroredHandlerData = {
  50. ...handlerData,
  51. endTimestamp: Date.now(),
  52. error,
  53. };
  54. _handlers.triggerHandlers('fetch', erroredHandlerData);
  55. // NOTE: If you are a Sentry user, and you are seeing this stack frame,
  56. // it means the sentry.javascript SDK caught an error invoking your application code.
  57. // This is expected behavior and NOT indicative of a bug with sentry.javascript.
  58. throw error;
  59. },
  60. );
  61. };
  62. });
  63. }
  64. function hasProp(obj, prop) {
  65. return !!obj && typeof obj === 'object' && !!(obj )[prop];
  66. }
  67. function getUrlFromResource(resource) {
  68. if (typeof resource === 'string') {
  69. return resource;
  70. }
  71. if (!resource) {
  72. return '';
  73. }
  74. if (hasProp(resource, 'url')) {
  75. return resource.url;
  76. }
  77. if (resource.toString) {
  78. return resource.toString();
  79. }
  80. return '';
  81. }
  82. /**
  83. * Parses the fetch arguments to find the used Http method and the url of the request.
  84. * Exported for tests only.
  85. */
  86. function parseFetchArgs(fetchArgs) {
  87. if (fetchArgs.length === 0) {
  88. return { method: 'GET', url: '' };
  89. }
  90. if (fetchArgs.length === 2) {
  91. const [url, options] = fetchArgs ;
  92. return {
  93. url: getUrlFromResource(url),
  94. method: hasProp(options, 'method') ? String(options.method).toUpperCase() : 'GET',
  95. };
  96. }
  97. const arg = fetchArgs[0];
  98. return {
  99. url: getUrlFromResource(arg ),
  100. method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',
  101. };
  102. }
  103. exports.addFetchInstrumentationHandler = addFetchInstrumentationHandler;
  104. exports.parseFetchArgs = parseFetchArgs;
  105. //# sourceMappingURL=fetch.js.map