Navigation

Node.js

How to Make HTTP Requests with Axios

Make HTTP requests in Node.js using Axios library. Popular HTTP client with interceptors, automatic JSON parsing, and comprehensive error handling features.

Table Of Contents

Problem

You need a feature-rich HTTP client for Node.js with automatic JSON parsing, request/response interceptors, timeout handling, and better error management than the basic fetch() API.

Solution

const axios = require('axios');

// 1. Basic GET Request
async function basicGet() {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
    
    console.log('Status:', response.status);
    console.log('Headers:', response.headers);
    console.log('Data:', response.data); // Automatically parsed JSON
    
    return response.data;
  } catch (error) {
    console.error('GET error:', error.message);
    throw error;
  }
}

// 2. POST Request with JSON Data
async function postData(postData) {
  try {
    const response = await axios.post('https://jsonplaceholder.typicode.com/posts', postData, {
      headers: {
        'Content-Type': 'application/json',
        'User-Agent': 'MyApp/1.0'
      }
    });
    
    console.log('Created post:', response.data);
    return response.data;
  } catch (error) {
    console.error('POST error:', error.response?.data || error.message);
    throw error;
  }
}

// 3. Axios Instance with Base Configuration
const apiClient = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
});

// Using the configured instance
async function useApiClient() {
  try {
    const response = await apiClient.get('/posts/1');
    return response.data;
  } catch (error) {
    console.error('API client error:', error.message);
    throw error;
  }
}

// 4. Request and Response Interceptors
apiClient.interceptors.request.use(
  (config) => {
    // Add auth token to requests
    const token = process.env.API_TOKEN;
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    console.log(`Making ${config.method?.toUpperCase()} request to ${config.url}`);
    return config;
  },
  (error) => {
    console.error('Request interceptor error:', error);
    return Promise.reject(error);
  }
);

apiClient.interceptors.response.use(
  (response) => {
    console.log(`Response received: ${response.status} ${response.statusText}`);
    return response;
  },
  (error) => {
    if (error.response?.status === 401) {
      console.error('Unauthorized request - token may be invalid');
    }
    
    console.error('Response interceptor error:', error.response?.status);
    return Promise.reject(error);
  }
);

// 5. Multiple Request Methods
async function allHttpMethods() {
  const baseUrl = 'https://jsonplaceholder.typicode.com';
  
  try {
    // GET
    const getResponse = await axios.get(`${baseUrl}/posts/1`);
    
    // POST
    const postResponse = await axios.post(`${baseUrl}/posts`, {
      title: 'New Post',
      body: 'Post content',
      userId: 1
    });
    
    // PUT
    const putResponse = await axios.put(`${baseUrl}/posts/1`, {
      id: 1,
      title: 'Updated Post',
      body: 'Updated content',
      userId: 1
    });
    
    // PATCH
    const patchResponse = await axios.patch(`${baseUrl}/posts/1`, {
      title: 'Patched Title'
    });
    
    // DELETE
    const deleteResponse = await axios.delete(`${baseUrl}/posts/1`);
    
    return {
      get: getResponse.data,
      post: postResponse.data,
      put: putResponse.data,
      patch: patchResponse.data,
      delete: deleteResponse.status
    };
  } catch (error) {
    console.error('HTTP methods error:', error.message);
    throw error;
  }
}

// 6. Form Data and File Upload
const FormData = require('form-data');
const fs = require('fs');

async function uploadFile(filePath, additionalData) {
  try {
    const formData = new FormData();
    formData.append('file', fs.createReadStream(filePath));
    formData.append('description', additionalData.description);
    formData.append('category', additionalData.category);
    
    const response = await axios.post('https://httpbin.org/post', formData, {
      headers: {
        ...formData.getHeaders(), // Important for multipart/form-data
      },
      maxContentLength: Infinity,
      maxBodyLength: Infinity
    });
    
    return response.data;
  } catch (error) {
    console.error('Upload error:', error.message);
    throw error;
  }
}

// 7. Request Cancellation
async function cancellableRequest() {
  const controller = new AbortController();
  
  // Cancel request after 3 seconds
  setTimeout(() => {
    controller.abort();
  }, 3000);
  
  try {
    const response = await axios.get('https://httpbin.org/delay/5', {
      signal: controller.signal
    });
    
    return response.data;
  } catch (error) {
    if (axios.isCancel(error)) {
      console.log('Request was cancelled');
      throw new Error('Request cancelled by user');
    }
    throw error;
  }
}

// 8. Concurrent Requests
async function concurrentRequests() {
  try {
    const requests = [
      axios.get('https://jsonplaceholder.typicode.com/posts/1'),
      axios.get('https://jsonplaceholder.typicode.com/posts/2'),
      axios.get('https://jsonplaceholder.typicode.com/posts/3')
    ];
    
    const responses = await Promise.allSettled(requests);
    
    return responses.map((response, index) => {
      if (response.status === 'fulfilled') {
        return {
          success: true,
          data: response.value.data
        };
      } else {
        return {
          success: false,
          error: response.reason.message
        };
      }
    });
  } catch (error) {
    console.error('Concurrent requests error:', error.message);
    throw error;
  }
}

// 9. Retry Logic with Axios
async function axiosWithRetry(url, options = {}, maxRetries = 3) {
  let lastError;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`Attempt ${attempt} of ${maxRetries}`);
      
      const response = await axios.get(url, options);
      return response;
    } catch (error) {
      lastError = error;
      
      // Don't retry on client errors (4xx)
      if (error.response?.status >= 400 && error.response?.status < 500) {
        throw error;
      }
      
      if (attempt === maxRetries) {
        break;
      }
      
      // Exponential backoff
      const delay = Math.pow(2, attempt - 1) * 1000;
      console.log(`Retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
  
  throw lastError;
}

// 10. Comprehensive Error Handling
async function handleAxiosErrors(url) {
  try {
    const response = await axios.get(url);
    return response.data;
  } catch (error) {
    if (error.response) {
      // Server responded with error status
      console.error('Response error:', {
        status: error.response.status,
        statusText: error.response.statusText,
        data: error.response.data,
        headers: error.response.headers
      });
      
      throw new Error(`HTTP ${error.response.status}: ${error.response.statusText}`);
    } else if (error.request) {
      // Request was made but no response received
      console.error('Request error:', error.request);
      throw new Error('No response received from server');
    } else {
      // Something else happened
      console.error('Setup error:', error.message);
      throw new Error(`Request setup error: ${error.message}`);
    }
  }
}

// 11. Custom Axios Configuration
const customAxios = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  validateStatus: (status) => {
    // Consider 2xx and 3xx as success
    return status >= 200 && status < 400;
  },
  transformRequest: [
    (data, headers) => {
      // Transform request data
      if (typeof data === 'object') {
        return JSON.stringify(data);
      }
      return data;
    }
  ],
  transformResponse: [
    (data) => {
      // Transform response data
      try {
        return JSON.parse(data);
      } catch (error) {
        return data;
      }
    }
  ]
});

// Usage examples
async function runExamples() {
  try {
    // Basic GET
    const getData = await basicGet();
    console.log('Basic GET:', getData.title);
    
    // POST request
    const postResult = await postData({
      title: 'My Axios Post',
      body: 'Content created with Axios',
      userId: 1
    });
    console.log('POST result:', postResult.id);
    
    // Multiple HTTP methods
    const allMethods = await allHttpMethods();
    console.log('All methods completed');
    
    // Concurrent requests
    const concurrent = await concurrentRequests();
    console.log('Concurrent requests:', concurrent.length);
    
    // Retry logic
    const retryResult = await axiosWithRetry('https://httpbin.org/status/500');
    console.log('Retry result:', retryResult.status);
    
  } catch (error) {
    console.error('Example error:', error.message);
  }
}

// Install axios first: npm install axios
if (require.main === module) {
  runExamples();
}

module.exports = {
  basicGet,
  postData,
  apiClient,
  uploadFile,
  cancellableRequest,
  concurrentRequests,
  axiosWithRetry,
  handleAxiosErrors
};

Install Axios:

npm install axios
# For form data uploads
npm install form-data

Explanation

Axios is a feature-rich HTTP client that automatically parses JSON responses and provides better error handling than fetch(). It supports request/response interceptors for adding authentication, logging, and error handling globally.

Create axios instances with axios.create() for different APIs with their own base URLs and headers. Axios provides built-in support for request cancellation, timeouts, and concurrent requests with comprehensive error objects containing request/response details.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Node.js