adapters.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import utils from '../utils.js';
  2. import httpAdapter from './http.js';
  3. import xhrAdapter from './xhr.js';
  4. import * as fetchAdapter from './fetch.js';
  5. import AxiosError from '../core/AxiosError.js';
  6. /**
  7. * Known adapters mapping.
  8. * Provides environment-specific adapters for Axios:
  9. * - `http` for Node.js
  10. * - `xhr` for browsers
  11. * - `fetch` for fetch API-based requests
  12. *
  13. * @type {Object<string, Function|Object>}
  14. */
  15. const knownAdapters = {
  16. http: httpAdapter,
  17. xhr: xhrAdapter,
  18. fetch: {
  19. get: fetchAdapter.getFetch,
  20. },
  21. };
  22. // Assign adapter names for easier debugging and identification
  23. utils.forEach(knownAdapters, (fn, value) => {
  24. if (fn) {
  25. try {
  26. // Null-proto descriptors so a polluted Object.prototype.get cannot turn
  27. // these data descriptors into accessor descriptors on the way in.
  28. Object.defineProperty(fn, 'name', { __proto__: null, value });
  29. } catch (e) {
  30. // eslint-disable-next-line no-empty
  31. }
  32. Object.defineProperty(fn, 'adapterName', { __proto__: null, value });
  33. }
  34. });
  35. /**
  36. * Render a rejection reason string for unknown or unsupported adapters
  37. *
  38. * @param {string} reason
  39. * @returns {string}
  40. */
  41. const renderReason = (reason) => `- ${reason}`;
  42. /**
  43. * Check if the adapter is resolved (function, null, or false)
  44. *
  45. * @param {Function|null|false} adapter
  46. * @returns {boolean}
  47. */
  48. const isResolvedHandle = (adapter) =>
  49. utils.isFunction(adapter) || adapter === null || adapter === false;
  50. /**
  51. * Get the first suitable adapter from the provided list.
  52. * Tries each adapter in order until a supported one is found.
  53. * Throws an AxiosError if no adapter is suitable.
  54. *
  55. * @param {Array<string|Function>|string|Function} adapters - Adapter(s) by name or function.
  56. * @param {Object} config - Axios request configuration
  57. * @throws {AxiosError} If no suitable adapter is available
  58. * @returns {Function} The resolved adapter function
  59. */
  60. function getAdapter(adapters, config) {
  61. adapters = utils.isArray(adapters) ? adapters : [adapters];
  62. const { length } = adapters;
  63. let nameOrAdapter;
  64. let adapter;
  65. const rejectedReasons = {};
  66. for (let i = 0; i < length; i++) {
  67. nameOrAdapter = adapters[i];
  68. let id;
  69. adapter = nameOrAdapter;
  70. if (!isResolvedHandle(nameOrAdapter)) {
  71. adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
  72. if (adapter === undefined) {
  73. throw new AxiosError(`Unknown adapter '${id}'`);
  74. }
  75. }
  76. if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) {
  77. break;
  78. }
  79. rejectedReasons[id || '#' + i] = adapter;
  80. }
  81. if (!adapter) {
  82. const reasons = Object.entries(rejectedReasons).map(
  83. ([id, state]) =>
  84. `adapter ${id} ` +
  85. (state === false ? 'is not supported by the environment' : 'is not available in the build')
  86. );
  87. let s = length
  88. ? reasons.length > 1
  89. ? 'since :\n' + reasons.map(renderReason).join('\n')
  90. : ' ' + renderReason(reasons[0])
  91. : 'as no adapter specified';
  92. throw new AxiosError(
  93. `There is no suitable adapter to dispatch the request ` + s,
  94. 'ERR_NOT_SUPPORT'
  95. );
  96. }
  97. return adapter;
  98. }
  99. /**
  100. * Exports Axios adapters and utility to resolve an adapter
  101. */
  102. export default {
  103. /**
  104. * Resolve an adapter from a list of adapter names or functions.
  105. * @type {Function}
  106. */
  107. getAdapter,
  108. /**
  109. * Exposes all known adapters
  110. * @type {Object<string, Function|Object>}
  111. */
  112. adapters: knownAdapters,
  113. };