CoolFace
Apppublic

opusdev/vector-similarity-api

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes
MIGRATION_GUIDE.md877 linesDownload Raw Back to axios
1# Axios Migration Guide2 3> **Migrating from Axios 0.x to 1.x**4> 5> This guide helps developers upgrade from Axios 0.x to 1.x by documenting breaking changes, providing migration strategies, and offering solutions to common upgrade challenges.6 7## Table of Contents8 9- [Overview](#overview)10- [Breaking Changes](#breaking-changes)11- [Error Handling Migration](#error-handling-migration)12- [API Changes](#api-changes)13- [Configuration Changes](#configuration-changes)14- [Migration Strategies](#migration-strategies)15- [Common Patterns](#common-patterns)16- [Troubleshooting](#troubleshooting)17- [Resources](#resources)18 19## Overview20 21Axios 1.x introduced several breaking changes to improve consistency, security, and developer experience. While these changes provide better error handling and more predictable behavior, they require code updates when migrating from 0.x versions.22 23### Key Changes Summary24 25| Area | 0.x Behavior | 1.x Behavior | Impact |26|------|--------------|--------------|--------|27| Error Handling | Selective throwing | Consistent throwing | High |28| JSON Parsing | Lenient | Strict | Medium |29| Browser Support | IE11+ | Modern browsers | Low-Medium |30| TypeScript | Partial | Full support | Low |31 32### Migration Complexity33 34- **Simple applications**: 1-2 hours35- **Medium applications**: 1-2 days  36- **Large applications with complex error handling**: 3-5 days37 38## Breaking Changes39 40### 1. Error Handling Changes41 42**The most significant change in Axios 1.x is how errors are handled.**43 44#### 0.x Behavior45```javascript46// Axios 0.x - Some HTTP error codes didn't throw47axios.get('/api/data')48  .then(response => {49    // Response interceptor could handle all errors50    console.log('Success:', response.data);51  });52 53// Response interceptor handled everything54axios.interceptors.response.use(55  response => response,56  error => {57    handleError(error);58    // Error was "handled" and didn't propagate59  }60);61```62 63#### 1.x Behavior64```javascript65// Axios 1.x - All HTTP errors throw consistently66axios.get('/api/data')67  .then(response => {68    console.log('Success:', response.data);69  })70  .catch(error => {71    // Must handle errors at call site or they propagate72    console.error('Request failed:', error);73  });74 75// Response interceptor must re-throw or return rejected promise76axios.interceptors.response.use(77  response => response,78  error => {79    handleError(error);80    // Must explicitly handle propagation81    return Promise.reject(error); // or throw error;82  }83);84```85 86#### Impact87- **Response interceptors** can no longer "swallow" errors silently88- **Every API call** must handle errors explicitly or they become unhandled promise rejections89- **Centralized error handling** requires new patterns90 91### 2. JSON Parsing Changes92 93#### 0.x Behavior94```javascript95// Axios 0.x - Lenient JSON parsing96// Would attempt to parse even invalid JSON97response.data; // Might contain partial data or fallbacks98```99 100#### 1.x Behavior101```javascript102// Axios 1.x - Strict JSON parsing103// Throws clear errors for invalid JSON104try {105  const data = response.data;106} catch (error) {107  // Handle JSON parsing errors explicitly108}109```110 111### 3. Request/Response Transform Changes112 113#### 0.x Behavior114```javascript115// Implicit transformations with some edge cases116transformRequest: [function (data) {117  // Less predictable behavior118  return data;119}]120```121 122#### 1.x Behavior123```javascript124// More consistent transformation pipeline125transformRequest: [function (data, headers) {126  // Headers parameter always available127  // More predictable behavior128  return data;129}]130```131 132### 4. Browser Support Changes133 134- **0.x**: Supported IE11 and older browsers135- **1.x**: Requires modern browsers with Promise support136- **Polyfills**: May be needed for older browser support137 138## Error Handling Migration139 140The error handling changes are the most complex part of migrating to Axios 1.x. Here are proven strategies:141 142### Strategy 1: Centralized Error Handling with Error Boundary143 144```javascript145// Create a centralized error handler146class ApiErrorHandler {147  constructor() {148    this.setupInterceptors();149  }150 151  setupInterceptors() {152    axios.interceptors.response.use(153      response => response,154      error => {155        // Centralized error processing156        this.processError(error);157        158        // Return a resolved promise with error info for handled errors159        if (this.isHandledError(error)) {160          return Promise.resolve({161            data: null,162            error: this.normalizeError(error),163            handled: true164          });165        }166        167        // Re-throw unhandled errors168        return Promise.reject(error);169      }170    );171  }172 173  processError(error) {174    // Log errors175    console.error('API Error:', error);176    177    // Show user notifications178    if (error.response?.status === 401) {179      this.handleAuthError();180    } else if (error.response?.status >= 500) {181      this.showErrorNotification('Server error occurred');182    }183  }184 185  isHandledError(error) {186    // Define which errors are "handled" centrally187    const handledStatuses = [401, 403, 404, 422, 500, 502, 503];188    return handledStatuses.includes(error.response?.status);189  }190 191  normalizeError(error) {192    return {193      status: error.response?.status,194      message: error.response?.data?.message || error.message,195      code: error.response?.data?.code || error.code196    };197  }198 199  handleAuthError() {200    // Redirect to login, clear tokens, etc.201    localStorage.removeItem('token');202    window.location.href = '/login';203  }204 205  showErrorNotification(message) {206    // Show user-friendly error message207    console.error(message); // Replace with your notification system208  }209}210 211// Initialize globally212const errorHandler = new ApiErrorHandler();213 214// Usage in components/services215async function fetchUserData(userId) {216  try {217    const response = await axios.get(`/api/users/${userId}`);218    219    // Check if error was handled centrally220    if (response.handled) {221      return { data: null, error: response.error };222    }223    224    return { data: response.data, error: null };225  } catch (error) {226    // Unhandled errors still need local handling227    return { data: null, error: { message: 'Unexpected error occurred' } };228  }229}230```231 232### Strategy 2: Wrapper Function Pattern233 234```javascript235// Create a wrapper that provides 0.x-like behavior236function createApiWrapper() {237  const api = axios.create();238  239  // Add response interceptor for centralized handling240  api.interceptors.response.use(241    response => response,242    error => {243      // Handle common errors centrally244      if (error.response?.status === 401) {245        // Handle auth errors246        handleAuthError();247      }248      249      if (error.response?.status >= 500) {250        // Handle server errors251        showServerErrorNotification();252      }253      254      // Always reject to maintain error propagation255      return Promise.reject(error);256    }257  );258 259  // Wrapper function that mimics 0.x behavior260  function safeRequest(requestConfig, options = {}) {261    return api(requestConfig)262      .then(response => response)263      .catch(error => {264        if (options.suppressErrors) {265          // Return error info instead of throwing266          return {267            data: null,268            error: {269              status: error.response?.status,270              message: error.response?.data?.message || error.message271            }272          };273        }274        throw error;275      });276  }277 278  return { safeRequest, axios: api };279}280 281// Usage282const { safeRequest } = createApiWrapper();283 284// For calls where you want centralized error handling285const result = await safeRequest(286  { method: 'get', url: '/api/data' },287  { suppressErrors: true }288);289 290if (result.error) {291  // Handle error case292  console.log('Request failed:', result.error.message);293} else {294  // Handle success case295  console.log('Data:', result.data);296}297```298 299### Strategy 3: Global Error Handler with Custom Events300 301```javascript302// Set up global error handling with events303class GlobalErrorHandler extends EventTarget {304  constructor() {305    super();306    this.setupInterceptors();307  }308 309  setupInterceptors() {310    axios.interceptors.response.use(311      response => response,312      error => {313        // Emit custom event for global handling314        this.dispatchEvent(new CustomEvent('apiError', {315          detail: { error, timestamp: new Date() }316        }));317 318        // Always reject to maintain proper error flow319        return Promise.reject(error);320      }321    );322  }323}324 325const globalErrorHandler = new GlobalErrorHandler();326 327// Set up global listeners328globalErrorHandler.addEventListener('apiError', (event) => {329  const { error } = event.detail;330  331  // Centralized error logic332  if (error.response?.status === 401) {333    handleAuthError();334  }335  336  if (error.response?.status >= 500) {337    showErrorNotification('Server error occurred');338  }339});340 341// Usage remains clean342async function apiCall() {343  try {344    const response = await axios.get('/api/data');345    return response.data;346  } catch (error) {347    // Error was already handled globally348    // Just handle component-specific logic349    return null;350  }351}352```353 354## API Changes355 356### Request Configuration357 358#### 0.x to 1.x Changes359```javascript360// 0.x - Some properties had different defaults361const config = {362  timeout: 0, // No timeout by default363  maxContentLength: -1, // No limit364};365 366// 1.x - More secure defaults367const config = {368  timeout: 0, // Still no timeout, but easier to configure369  maxContentLength: 2000, // Default limit for security370  maxBodyLength: 2000, // New property371};372```373 374### Response Object375 376The response object structure remains largely the same, but error responses are more consistent:377 378```javascript379// Both 0.x and 1.x380response = {381  data: {}, // Response body382  status: 200, // HTTP status383  statusText: 'OK', // HTTP status message  384  headers: {}, // Response headers385  config: {}, // Request config386  request: {} // Request object387};388 389// Error responses are more consistent in 1.x390error.response = {391  data: {}, // Error response body392  status: 404, // HTTP error status393  statusText: 'Not Found',394  headers: {},395  config: {},396  request: {}397};398```399 400## Configuration Changes401 402### Default Configuration Updates403 404```javascript405// 0.x defaults406axios.defaults.timeout = 0; // No timeout407axios.defaults.maxContentLength = -1; // No limit408 409// 1.x defaults (more secure)410axios.defaults.timeout = 0; // Still no timeout411axios.defaults.maxContentLength = 2000; // 2MB limit412axios.defaults.maxBodyLength = 2000; // 2MB limit413```414 415### Instance Configuration416 417```javascript418// 0.x - Instance creation419const api = axios.create({420  baseURL: 'https://api.example.com',421  timeout: 1000,422});423 424// 1.x - Same API, but more options available425const api = axios.create({426  baseURL: 'https://api.example.com',427  timeout: 1000,428  maxBodyLength: Infinity, // Override default if needed429  maxContentLength: Infinity,430});431```432 433## Migration Strategies434 435### Step-by-Step Migration Process436 437#### Phase 1: Preparation4381. **Audit Current Error Handling**439   ```bash440   # Find all axios usage441   grep -r "axios\." src/442   grep -r "\.catch" src/443   grep -r "interceptors" src/444   ```445 4462. **Identify Patterns**447   - Response interceptors that handle errors448   - Components that rely on centralized error handling449   - Authentication and retry logic450 4513. **Create Test Cases**452   ```javascript453   // Test current error handling behavior454   describe('Error Handling Migration', () => {455     it('should handle 401 errors consistently', async () => {456       // Test authentication error flows457     });458     459     it('should handle 500 errors with user feedback', async () => {460       // Test server error handling461     });462   });463   ```464 465#### Phase 2: Implementation4661. **Update Dependencies**467   ```bash468   npm update axios469   ```470 4712. **Implement New Error Handling**472   - Choose one of the strategies above473   - Update response interceptors474   - Add error handling to API calls475 4763. **Update Authentication Logic**477   ```javascript478   // 0.x pattern479   axios.interceptors.response.use(null, error => {480     if (error.response?.status === 401) {481       logout();482       // Error was "handled"483     }484   });485 486   // 1.x pattern487   axios.interceptors.response.use(488     response => response,489     error => {490       if (error.response?.status === 401) {491         logout();492       }493       return Promise.reject(error); // Always propagate494     }495   );496   ```497 498#### Phase 3: Testing and Validation4991. **Test Error Scenarios**500   - Network failures501   - HTTP error codes (401, 403, 404, 500, etc.)502   - Timeout errors503   - JSON parsing errors504 5052. **Validate User Experience**506   - Error messages are shown appropriately507   - Authentication redirects work508   - Loading states are handled correctly509 510### Gradual Migration Approach511 512For large applications, consider gradual migration:513 514```javascript515// Create a compatibility layer516const axiosCompat = {517  // Use new axios instance for new code518  v1: axios.create({519    // 1.x configuration520  }),521  522  // Wrapper for legacy code523  legacy: createLegacyWrapper(axios.create({524    // Configuration that mimics 0.x behavior525  }))526};527 528function createLegacyWrapper(axiosInstance) {529  // Add interceptors that provide 0.x-like behavior530  axiosInstance.interceptors.response.use(531    response => response,532    error => {533      // Handle errors in 0.x style for legacy code534      handleLegacyError(error);535      // Don't propagate certain errors536      if (shouldSuppressError(error)) {537        return Promise.resolve({ data: null, error: true });538      }539      return Promise.reject(error);540    }541  );542  543  return axiosInstance;544}545```546 547## Common Patterns548 549### Authentication Interceptors550 551#### Updated Authentication Pattern552```javascript553// Token refresh interceptor for 1.x554let isRefreshing = false;555let refreshSubscribers = [];556 557function subscribeTokenRefresh(cb) {558  refreshSubscribers.push(cb);559}560 561function onTokenRefreshed(token) {562  refreshSubscribers.forEach(cb => cb(token));563  refreshSubscribers = [];564}565 566axios.interceptors.response.use(567  response => response,568  async error => {569    const originalRequest = error.config;570    571    if (error.response?.status === 401 && !originalRequest._retry) {572      if (isRefreshing) {573        // Wait for token refresh574        return new Promise(resolve => {575          subscribeTokenRefresh(token => {576            originalRequest.headers.Authorization = `Bearer ${token}`;577            resolve(axios(originalRequest));578          });579        });580      }581      582      originalRequest._retry = true;583      isRefreshing = true;584      585      try {586        const newToken = await refreshToken();587        onTokenRefreshed(newToken);588        isRefreshing = false;589        590        originalRequest.headers.Authorization = `Bearer ${newToken}`;591        return axios(originalRequest);592      } catch (refreshError) {593        isRefreshing = false;594        logout();595        return Promise.reject(refreshError);596      }597    }598    599    return Promise.reject(error);600  }601);602```603 604### Retry Logic605 606```javascript607// Retry interceptor for 1.x608function createRetryInterceptor(maxRetries = 3, retryDelay = 1000) {609  return axios.interceptors.response.use(610    response => response,611    async error => {612      const config = error.config;613      614      if (!config || !config.retry) {615        return Promise.reject(error);616      }617      618      config.__retryCount = config.__retryCount || 0;619      620      if (config.__retryCount >= maxRetries) {621        return Promise.reject(error);622      }623      624      config.__retryCount += 1;625      626      // Exponential backoff627      const delay = retryDelay * Math.pow(2, config.__retryCount - 1);628      await new Promise(resolve => setTimeout(resolve, delay));629      630      return axios(config);631    }632  );633}634 635// Usage636const api = axios.create();637createRetryInterceptor(3, 1000);638 639// Make request with retry640api.get('/api/data', { retry: true });641```642 643### Loading State Management644 645```javascript646// Loading interceptor for 1.x647class LoadingManager {648  constructor() {649    this.requests = new Set();650    this.setupInterceptors();651  }652  653  setupInterceptors() {654    axios.interceptors.request.use(config => {655      this.requests.add(config);656      this.updateLoadingState();657      return config;658    });659    660    axios.interceptors.response.use(661      response => {662        this.requests.delete(response.config);663        this.updateLoadingState();664        return response;665      },666      error => {667        this.requests.delete(error.config);668        this.updateLoadingState();669        return Promise.reject(error);670      }671    );672  }673  674  updateLoadingState() {675    const isLoading = this.requests.size > 0;676    // Update your loading UI677    document.body.classList.toggle('loading', isLoading);678  }679}680 681const loadingManager = new LoadingManager();682```683 684## Troubleshooting685 686### Common Migration Issues687 688#### Issue 1: Unhandled Promise Rejections689 690**Problem:**691```javascript692// This pattern worked in 0.x but causes unhandled rejections in 1.x693axios.get('/api/data'); // No .catch() handler694```695 696**Solution:**697```javascript698// Always handle promises699axios.get('/api/data')700  .catch(error => {701    // Handle error appropriately702    console.error('Request failed:', error.message);703  });704 705// Or use async/await with try/catch706async function fetchData() {707  try {708    const response = await axios.get('/api/data');709    return response.data;710  } catch (error) {711    console.error('Request failed:', error.message);712    return null;713  }714}715```716 717#### Issue 2: Response Interceptors Not "Handling" Errors718 719**Problem:**720```javascript721// 0.x style - interceptor "handled" errors722axios.interceptors.response.use(null, error => {723  showErrorMessage(error.message);724  // Error was considered "handled"725});726```727 728**Solution:**729```javascript730// 1.x style - explicitly control error propagation731axios.interceptors.response.use(732  response => response,733  error => {734    showErrorMessage(error.message);735    736    // Choose whether to propagate the error737    if (shouldPropagateError(error)) {738      return Promise.reject(error);739    }740    741    // Return success-like response for "handled" errors742    return Promise.resolve({743      data: null,744      handled: true,745      error: normalizeError(error)746    });747  }748);749```750 751#### Issue 3: JSON Parsing Errors752 753**Problem:**754```javascript755// 1.x is stricter about JSON parsing756// This might throw where 0.x was lenient757const data = response.data;758```759 760**Solution:**761```javascript762// Add response transformer for better error handling763axios.defaults.transformResponse = [764  function (data) {765    if (typeof data === 'string') {766      try {767        return JSON.parse(data);768      } catch (e) {769        // Handle JSON parsing errors gracefully770        console.warn('Invalid JSON response:', data);771        return { error: 'Invalid JSON', rawData: data };772      }773    }774    return data;775  }776];777```778 779#### Issue 4: TypeScript Errors After Upgrade780 781**Problem:**782```typescript783// TypeScript errors after upgrade784const response = await axios.get('/api/data');785// Property 'someProperty' does not exist on type 'any'786```787 788**Solution:**789```typescript790// Define proper interfaces791interface ApiResponse {792  data: any;793  message: string;794  success: boolean;795}796 797const response = await axios.get<ApiResponse>('/api/data');798// Now properly typed799console.log(response.data.data);800```801 802### Debug Migration Issues803 804#### Enable Debug Logging805```javascript806// Add request/response logging807axios.interceptors.request.use(config => {808  console.log('Request:', config);809  return config;810});811 812axios.interceptors.response.use(813  response => {814    console.log('Response:', response);815    return response;816  },817  error => {818    console.log('Error:', error);819    return Promise.reject(error);820  }821);822```823 824#### Compare Behavior825```javascript826// Create side-by-side comparison during migration827const axios0x = require('axios-0x'); // Keep old version for testing828const axios1x = require('axios');829 830async function compareRequests(config) {831  try {832    const [result0x, result1x] = await Promise.allSettled([833      axios0x(config),834      axios1x(config)835    ]);836    837    console.log('0.x result:', result0x);838    console.log('1.x result:', result1x);839  } catch (error) {840    console.log('Comparison error:', error);841  }842}843```844 845## Resources846 847### Official Documentation848- [Axios 1.x Documentation](https://axios-http.com/)849- [Axios GitHub Repository](https://github.com/axios/axios)850- [Axios Changelog](https://github.com/axios/axios/blob/main/CHANGELOG.md)851 852### Migration Tools853- [Axios Migration Codemod](https://github.com/axios/axios-migration-codemod) *(if available)*854- [ESLint Rules for Axios 1.x](https://github.com/axios/eslint-plugin-axios) *(if available)*855 856### Community Resources857- [Stack Overflow - Axios Migration Questions](https://stackoverflow.com/questions/tagged/axios+migration)858- [GitHub Discussions](https://github.com/axios/axios/discussions)859- [Axios Discord Community](https://discord.gg/axios) *(if available)*860 861### Related Issues862- [Error Handling Changes Discussion](https://github.com/axios/axios/issues/7208)863- [Migration Guide Request](https://github.com/axios/axios/issues/xxxx) *(link to related issues)*864 865---866 867## Need Help?868 869If you encounter issues during migration that aren't covered in this guide:870 8711. **Search existing issues** in the [Axios GitHub repository](https://github.com/axios/axios/issues)8722. **Ask questions** in [GitHub Discussions](https://github.com/axios/axios/discussions)8733. **Contribute improvements** to this migration guide874 875---876 877*This migration guide is maintained by the community. If you find errors or have suggestions, please [open an issue](https://github.com/axios/axios/issues) or submit a pull request.*