axios 1.13.2 → 1.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,877 @@
1
- # Migration Guide
1
+ # Axios Migration Guide
2
2
 
3
- ## 0.x.x -> 1.1.0
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 Contents
8
+
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
+ ## Overview
20
+
21
+ Axios 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 Summary
24
+
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 Complexity
33
+
34
+ - **Simple applications**: 1-2 hours
35
+ - **Medium applications**: 1-2 days
36
+ - **Large applications with complex error handling**: 3-5 days
37
+
38
+ ## Breaking Changes
39
+
40
+ ### 1. Error Handling Changes
41
+
42
+ **The most significant change in Axios 1.x is how errors are handled.**
43
+
44
+ #### 0.x Behavior
45
+ ```javascript
46
+ // Axios 0.x - Some HTTP error codes didn't throw
47
+ axios.get('/api/data')
48
+ .then(response => {
49
+ // Response interceptor could handle all errors
50
+ console.log('Success:', response.data);
51
+ });
52
+
53
+ // Response interceptor handled everything
54
+ axios.interceptors.response.use(
55
+ response => response,
56
+ error => {
57
+ handleError(error);
58
+ // Error was "handled" and didn't propagate
59
+ }
60
+ );
61
+ ```
62
+
63
+ #### 1.x Behavior
64
+ ```javascript
65
+ // Axios 1.x - All HTTP errors throw consistently
66
+ axios.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 propagate
72
+ console.error('Request failed:', error);
73
+ });
74
+
75
+ // Response interceptor must re-throw or return rejected promise
76
+ axios.interceptors.response.use(
77
+ response => response,
78
+ error => {
79
+ handleError(error);
80
+ // Must explicitly handle propagation
81
+ return Promise.reject(error); // or throw error;
82
+ }
83
+ );
84
+ ```
85
+
86
+ #### Impact
87
+ - **Response interceptors** can no longer "swallow" errors silently
88
+ - **Every API call** must handle errors explicitly or they become unhandled promise rejections
89
+ - **Centralized error handling** requires new patterns
90
+
91
+ ### 2. JSON Parsing Changes
92
+
93
+ #### 0.x Behavior
94
+ ```javascript
95
+ // Axios 0.x - Lenient JSON parsing
96
+ // Would attempt to parse even invalid JSON
97
+ response.data; // Might contain partial data or fallbacks
98
+ ```
99
+
100
+ #### 1.x Behavior
101
+ ```javascript
102
+ // Axios 1.x - Strict JSON parsing
103
+ // Throws clear errors for invalid JSON
104
+ try {
105
+ const data = response.data;
106
+ } catch (error) {
107
+ // Handle JSON parsing errors explicitly
108
+ }
109
+ ```
110
+
111
+ ### 3. Request/Response Transform Changes
112
+
113
+ #### 0.x Behavior
114
+ ```javascript
115
+ // Implicit transformations with some edge cases
116
+ transformRequest: [function (data) {
117
+ // Less predictable behavior
118
+ return data;
119
+ }]
120
+ ```
121
+
122
+ #### 1.x Behavior
123
+ ```javascript
124
+ // More consistent transformation pipeline
125
+ transformRequest: [function (data, headers) {
126
+ // Headers parameter always available
127
+ // More predictable behavior
128
+ return data;
129
+ }]
130
+ ```
131
+
132
+ ### 4. Browser Support Changes
133
+
134
+ - **0.x**: Supported IE11 and older browsers
135
+ - **1.x**: Requires modern browsers with Promise support
136
+ - **Polyfills**: May be needed for older browser support
137
+
138
+ ## Error Handling Migration
139
+
140
+ The 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 Boundary
143
+
144
+ ```javascript
145
+ // Create a centralized error handler
146
+ class ApiErrorHandler {
147
+ constructor() {
148
+ this.setupInterceptors();
149
+ }
150
+
151
+ setupInterceptors() {
152
+ axios.interceptors.response.use(
153
+ response => response,
154
+ error => {
155
+ // Centralized error processing
156
+ this.processError(error);
157
+
158
+ // Return a resolved promise with error info for handled errors
159
+ if (this.isHandledError(error)) {
160
+ return Promise.resolve({
161
+ data: null,
162
+ error: this.normalizeError(error),
163
+ handled: true
164
+ });
165
+ }
166
+
167
+ // Re-throw unhandled errors
168
+ return Promise.reject(error);
169
+ }
170
+ );
171
+ }
172
+
173
+ processError(error) {
174
+ // Log errors
175
+ console.error('API Error:', error);
176
+
177
+ // Show user notifications
178
+ 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" centrally
187
+ 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.code
196
+ };
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 message
207
+ console.error(message); // Replace with your notification system
208
+ }
209
+ }
210
+
211
+ // Initialize globally
212
+ const errorHandler = new ApiErrorHandler();
213
+
214
+ // Usage in components/services
215
+ async function fetchUserData(userId) {
216
+ try {
217
+ const response = await axios.get(`/api/users/${userId}`);
218
+
219
+ // Check if error was handled centrally
220
+ 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 handling
227
+ return { data: null, error: { message: 'Unexpected error occurred' } };
228
+ }
229
+ }
230
+ ```
231
+
232
+ ### Strategy 2: Wrapper Function Pattern
233
+
234
+ ```javascript
235
+ // Create a wrapper that provides 0.x-like behavior
236
+ function createApiWrapper() {
237
+ const api = axios.create();
238
+
239
+ // Add response interceptor for centralized handling
240
+ api.interceptors.response.use(
241
+ response => response,
242
+ error => {
243
+ // Handle common errors centrally
244
+ if (error.response?.status === 401) {
245
+ // Handle auth errors
246
+ handleAuthError();
247
+ }
248
+
249
+ if (error.response?.status >= 500) {
250
+ // Handle server errors
251
+ showServerErrorNotification();
252
+ }
253
+
254
+ // Always reject to maintain error propagation
255
+ return Promise.reject(error);
256
+ }
257
+ );
258
+
259
+ // Wrapper function that mimics 0.x behavior
260
+ 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 throwing
266
+ return {
267
+ data: null,
268
+ error: {
269
+ status: error.response?.status,
270
+ message: error.response?.data?.message || error.message
271
+ }
272
+ };
273
+ }
274
+ throw error;
275
+ });
276
+ }
277
+
278
+ return { safeRequest, axios: api };
279
+ }
280
+
281
+ // Usage
282
+ const { safeRequest } = createApiWrapper();
283
+
284
+ // For calls where you want centralized error handling
285
+ const result = await safeRequest(
286
+ { method: 'get', url: '/api/data' },
287
+ { suppressErrors: true }
288
+ );
289
+
290
+ if (result.error) {
291
+ // Handle error case
292
+ console.log('Request failed:', result.error.message);
293
+ } else {
294
+ // Handle success case
295
+ console.log('Data:', result.data);
296
+ }
297
+ ```
298
+
299
+ ### Strategy 3: Global Error Handler with Custom Events
300
+
301
+ ```javascript
302
+ // Set up global error handling with events
303
+ class 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 handling
314
+ this.dispatchEvent(new CustomEvent('apiError', {
315
+ detail: { error, timestamp: new Date() }
316
+ }));
317
+
318
+ // Always reject to maintain proper error flow
319
+ return Promise.reject(error);
320
+ }
321
+ );
322
+ }
323
+ }
324
+
325
+ const globalErrorHandler = new GlobalErrorHandler();
326
+
327
+ // Set up global listeners
328
+ globalErrorHandler.addEventListener('apiError', (event) => {
329
+ const { error } = event.detail;
330
+
331
+ // Centralized error logic
332
+ 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 clean
342
+ async function apiCall() {
343
+ try {
344
+ const response = await axios.get('/api/data');
345
+ return response.data;
346
+ } catch (error) {
347
+ // Error was already handled globally
348
+ // Just handle component-specific logic
349
+ return null;
350
+ }
351
+ }
352
+ ```
353
+
354
+ ## API Changes
355
+
356
+ ### Request Configuration
357
+
358
+ #### 0.x to 1.x Changes
359
+ ```javascript
360
+ // 0.x - Some properties had different defaults
361
+ const config = {
362
+ timeout: 0, // No timeout by default
363
+ maxContentLength: -1, // No limit
364
+ };
365
+
366
+ // 1.x - More secure defaults
367
+ const config = {
368
+ timeout: 0, // Still no timeout, but easier to configure
369
+ maxContentLength: 2000, // Default limit for security
370
+ maxBodyLength: 2000, // New property
371
+ };
372
+ ```
373
+
374
+ ### Response Object
375
+
376
+ The response object structure remains largely the same, but error responses are more consistent:
377
+
378
+ ```javascript
379
+ // Both 0.x and 1.x
380
+ response = {
381
+ data: {}, // Response body
382
+ status: 200, // HTTP status
383
+ statusText: 'OK', // HTTP status message
384
+ headers: {}, // Response headers
385
+ config: {}, // Request config
386
+ request: {} // Request object
387
+ };
388
+
389
+ // Error responses are more consistent in 1.x
390
+ error.response = {
391
+ data: {}, // Error response body
392
+ status: 404, // HTTP error status
393
+ statusText: 'Not Found',
394
+ headers: {},
395
+ config: {},
396
+ request: {}
397
+ };
398
+ ```
399
+
400
+ ## Configuration Changes
401
+
402
+ ### Default Configuration Updates
403
+
404
+ ```javascript
405
+ // 0.x defaults
406
+ axios.defaults.timeout = 0; // No timeout
407
+ axios.defaults.maxContentLength = -1; // No limit
408
+
409
+ // 1.x defaults (more secure)
410
+ axios.defaults.timeout = 0; // Still no timeout
411
+ axios.defaults.maxContentLength = 2000; // 2MB limit
412
+ axios.defaults.maxBodyLength = 2000; // 2MB limit
413
+ ```
414
+
415
+ ### Instance Configuration
416
+
417
+ ```javascript
418
+ // 0.x - Instance creation
419
+ const api = axios.create({
420
+ baseURL: 'https://api.example.com',
421
+ timeout: 1000,
422
+ });
423
+
424
+ // 1.x - Same API, but more options available
425
+ const api = axios.create({
426
+ baseURL: 'https://api.example.com',
427
+ timeout: 1000,
428
+ maxBodyLength: Infinity, // Override default if needed
429
+ maxContentLength: Infinity,
430
+ });
431
+ ```
432
+
433
+ ## Migration Strategies
434
+
435
+ ### Step-by-Step Migration Process
436
+
437
+ #### Phase 1: Preparation
438
+ 1. **Audit Current Error Handling**
439
+ ```bash
440
+ # Find all axios usage
441
+ grep -r "axios\." src/
442
+ grep -r "\.catch" src/
443
+ grep -r "interceptors" src/
444
+ ```
445
+
446
+ 2. **Identify Patterns**
447
+ - Response interceptors that handle errors
448
+ - Components that rely on centralized error handling
449
+ - Authentication and retry logic
450
+
451
+ 3. **Create Test Cases**
452
+ ```javascript
453
+ // Test current error handling behavior
454
+ describe('Error Handling Migration', () => {
455
+ it('should handle 401 errors consistently', async () => {
456
+ // Test authentication error flows
457
+ });
458
+
459
+ it('should handle 500 errors with user feedback', async () => {
460
+ // Test server error handling
461
+ });
462
+ });
463
+ ```
464
+
465
+ #### Phase 2: Implementation
466
+ 1. **Update Dependencies**
467
+ ```bash
468
+ npm update axios
469
+ ```
470
+
471
+ 2. **Implement New Error Handling**
472
+ - Choose one of the strategies above
473
+ - Update response interceptors
474
+ - Add error handling to API calls
475
+
476
+ 3. **Update Authentication Logic**
477
+ ```javascript
478
+ // 0.x pattern
479
+ axios.interceptors.response.use(null, error => {
480
+ if (error.response?.status === 401) {
481
+ logout();
482
+ // Error was "handled"
483
+ }
484
+ });
485
+
486
+ // 1.x pattern
487
+ axios.interceptors.response.use(
488
+ response => response,
489
+ error => {
490
+ if (error.response?.status === 401) {
491
+ logout();
492
+ }
493
+ return Promise.reject(error); // Always propagate
494
+ }
495
+ );
496
+ ```
497
+
498
+ #### Phase 3: Testing and Validation
499
+ 1. **Test Error Scenarios**
500
+ - Network failures
501
+ - HTTP error codes (401, 403, 404, 500, etc.)
502
+ - Timeout errors
503
+ - JSON parsing errors
504
+
505
+ 2. **Validate User Experience**
506
+ - Error messages are shown appropriately
507
+ - Authentication redirects work
508
+ - Loading states are handled correctly
509
+
510
+ ### Gradual Migration Approach
511
+
512
+ For large applications, consider gradual migration:
513
+
514
+ ```javascript
515
+ // Create a compatibility layer
516
+ const axiosCompat = {
517
+ // Use new axios instance for new code
518
+ v1: axios.create({
519
+ // 1.x configuration
520
+ }),
521
+
522
+ // Wrapper for legacy code
523
+ legacy: createLegacyWrapper(axios.create({
524
+ // Configuration that mimics 0.x behavior
525
+ }))
526
+ };
527
+
528
+ function createLegacyWrapper(axiosInstance) {
529
+ // Add interceptors that provide 0.x-like behavior
530
+ axiosInstance.interceptors.response.use(
531
+ response => response,
532
+ error => {
533
+ // Handle errors in 0.x style for legacy code
534
+ handleLegacyError(error);
535
+ // Don't propagate certain errors
536
+ 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 Patterns
548
+
549
+ ### Authentication Interceptors
550
+
551
+ #### Updated Authentication Pattern
552
+ ```javascript
553
+ // Token refresh interceptor for 1.x
554
+ let isRefreshing = false;
555
+ let refreshSubscribers = [];
556
+
557
+ function subscribeTokenRefresh(cb) {
558
+ refreshSubscribers.push(cb);
559
+ }
560
+
561
+ function onTokenRefreshed(token) {
562
+ refreshSubscribers.forEach(cb => cb(token));
563
+ refreshSubscribers = [];
564
+ }
565
+
566
+ axios.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 refresh
574
+ 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 Logic
605
+
606
+ ```javascript
607
+ // Retry interceptor for 1.x
608
+ function 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 backoff
627
+ 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
+ // Usage
636
+ const api = axios.create();
637
+ createRetryInterceptor(3, 1000);
638
+
639
+ // Make request with retry
640
+ api.get('/api/data', { retry: true });
641
+ ```
642
+
643
+ ### Loading State Management
644
+
645
+ ```javascript
646
+ // Loading interceptor for 1.x
647
+ class 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 UI
677
+ document.body.classList.toggle('loading', isLoading);
678
+ }
679
+ }
680
+
681
+ const loadingManager = new LoadingManager();
682
+ ```
683
+
684
+ ## Troubleshooting
685
+
686
+ ### Common Migration Issues
687
+
688
+ #### Issue 1: Unhandled Promise Rejections
689
+
690
+ **Problem:**
691
+ ```javascript
692
+ // This pattern worked in 0.x but causes unhandled rejections in 1.x
693
+ axios.get('/api/data'); // No .catch() handler
694
+ ```
695
+
696
+ **Solution:**
697
+ ```javascript
698
+ // Always handle promises
699
+ axios.get('/api/data')
700
+ .catch(error => {
701
+ // Handle error appropriately
702
+ console.error('Request failed:', error.message);
703
+ });
704
+
705
+ // Or use async/await with try/catch
706
+ async 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" Errors
718
+
719
+ **Problem:**
720
+ ```javascript
721
+ // 0.x style - interceptor "handled" errors
722
+ axios.interceptors.response.use(null, error => {
723
+ showErrorMessage(error.message);
724
+ // Error was considered "handled"
725
+ });
726
+ ```
727
+
728
+ **Solution:**
729
+ ```javascript
730
+ // 1.x style - explicitly control error propagation
731
+ axios.interceptors.response.use(
732
+ response => response,
733
+ error => {
734
+ showErrorMessage(error.message);
735
+
736
+ // Choose whether to propagate the error
737
+ if (shouldPropagateError(error)) {
738
+ return Promise.reject(error);
739
+ }
740
+
741
+ // Return success-like response for "handled" errors
742
+ return Promise.resolve({
743
+ data: null,
744
+ handled: true,
745
+ error: normalizeError(error)
746
+ });
747
+ }
748
+ );
749
+ ```
750
+
751
+ #### Issue 3: JSON Parsing Errors
752
+
753
+ **Problem:**
754
+ ```javascript
755
+ // 1.x is stricter about JSON parsing
756
+ // This might throw where 0.x was lenient
757
+ const data = response.data;
758
+ ```
759
+
760
+ **Solution:**
761
+ ```javascript
762
+ // Add response transformer for better error handling
763
+ axios.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 gracefully
770
+ 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 Upgrade
780
+
781
+ **Problem:**
782
+ ```typescript
783
+ // TypeScript errors after upgrade
784
+ const response = await axios.get('/api/data');
785
+ // Property 'someProperty' does not exist on type 'any'
786
+ ```
787
+
788
+ **Solution:**
789
+ ```typescript
790
+ // Define proper interfaces
791
+ interface ApiResponse {
792
+ data: any;
793
+ message: string;
794
+ success: boolean;
795
+ }
796
+
797
+ const response = await axios.get<ApiResponse>('/api/data');
798
+ // Now properly typed
799
+ console.log(response.data.data);
800
+ ```
801
+
802
+ ### Debug Migration Issues
803
+
804
+ #### Enable Debug Logging
805
+ ```javascript
806
+ // Add request/response logging
807
+ axios.interceptors.request.use(config => {
808
+ console.log('Request:', config);
809
+ return config;
810
+ });
811
+
812
+ axios.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 Behavior
825
+ ```javascript
826
+ // Create side-by-side comparison during migration
827
+ const axios0x = require('axios-0x'); // Keep old version for testing
828
+ const axios1x = require('axios');
829
+
830
+ async 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
+ ## Resources
846
+
847
+ ### Official Documentation
848
+ - [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 Tools
853
+ - [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 Resources
857
+ - [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 Issues
862
+ - [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
+
869
+ If you encounter issues during migration that aren't covered in this guide:
870
+
871
+ 1. **Search existing issues** in the [Axios GitHub repository](https://github.com/axios/axios/issues)
872
+ 2. **Ask questions** in [GitHub Discussions](https://github.com/axios/axios/discussions)
873
+ 3. **Contribute improvements** to this migration guide
874
+
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.*