DEV Community

Cover image for How to master HTTP requests with Axios
Juan Cruz Martinez
Juan Cruz Martinez

Posted on • Originally published at livecodestream.dev on

How to master HTTP requests with Axios

Axios is one of the favorite HTTP clients among Javascript developers. It is a promise-based HTTP client used to send HTTP requests, especially AJAX requests, from the client side as well as the server side.

Sending HTTP requests from the Javascript side is now almost a necessity when developing dynamic web applications. Axios simplifies this task by providing an easy-to-use abstraction over Javascript’s XMLHttpRequest interface with several user-friendly functions and configuration options.

In this tutorial, we will walk through everything you need to know about sending HTTP requests with Axios with code examples and simplified explanations.

Let’s start our introduction with this question.


Why You Should Choose Axios?

Axios has several advantages over other HTTP clients, such as jQuery’s AJAX, the native XMLHttpRequest library, and fetch. It is a lightweight package with excellent support for client-side and server-side requests, which means it can run on NodeJS or the browser.

The syntax of Axios is simple and intuitive, making it easy to work with even for novice developers.

Recently the Fetch API has been gaining some popularity for sending requests. However, Axios still provides several advantages over the same:

  • Support for request and response interception
  • Ability to cancel Axios requests
  • Automatic transforms for JSON data (Axios serializes javascript objects into JSON and vice versa)
  • Automatic data object serialization to multipart/form-data and x-www-form-urlencoded body encodings
  • Client-side support for XSRF protection

How to install Axios

You can install and use Axios on both the front-end and back-end. The installation is simple if you are using a package manager like npm.

npm install axios
Enter fullscreen mode Exit fullscreen mode

If you use a content delivery network (CDN), embed the Axios script in HTML.

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

Or,

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

Send HTTP Requests with Axios

Axios is simple. To start an HTTP request, you can use the Axios main function, passing an object with all the request parameters, options, and data like in the following example:

axios({
    method: "post",
    url: "/users",
    data: {
        username: "sam123",
        firstname: "sam",
        lastname: "smith"
    }
});
Enter fullscreen mode Exit fullscreen mode

As can be identified, the Axios library will initiate a POST request against the given URL and send some data to the server.

That's a simple example, but Axios provides much more features that can be enabled in this request object. To learn more about it, refer to its official documentation.

That's way number one to send requests, but there is another, which I prefer as it is more explicit, which is using dedicated request functions for each HTTP method.

Here is the list of supported methods:

axios.delete(url[, config]);
axios.head(url[, config]);
axios.options(url[, config]);
axios.post(url[, data[, config]]);
axios.put(url[, data[, config]]);
axios.patch(url[, data[, config]]);
Enter fullscreen mode Exit fullscreen mode

Axios GET request example

The beauty of Axios is in its simplicity while giving the user multiple options. Say, for instance, that you need to make a GET request to the URL: /users?firstName=jc. You could simply write the following Axios GET request code:

axios.get('/user', {
    params: {
      firstName: 'jc'
    }
  })
  .then(function (response) {
    // handle success
    console.log(response);
  });
Enter fullscreen mode Exit fullscreen mode

But alternatively, you can pass the parameters as part of the URL string. However, This may not be a best practice; it's cleaner when working with variables, and Axios will automatically sanitize the inputs, which won't do if you provide the values directly as part of the URL.

But in some cases, it makes sense to avoid sanitization, e.g., when sending certain API keys over query parameters. Here is the same request not using params.

axios.get('/user?firstName=jc')
  .then(function (response) {
    // handle success
    console.log(response);
  });
Enter fullscreen mode Exit fullscreen mode

Both examples of Axios GET requests handle only the happy path, but since Axios is promise based, you can also catch errors and run code in either condition.

Axios POST Request Example

When working with POST requests (also similar to PATCH and PUT), it is very common to send data to the server, and if you are working with REST APIs, chances are you are sending data in JSON format. The beauty of Axios in working with REST is that it will automatically transform JS objects into JSON when sending data and will convert the responses from JSON into JS objects so that you can directly work with them.

Let's see an example of an Axios POST request.

axios.post('/user', {
    firstName: 'jc',
    lastName: 'M'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
Enter fullscreen mode Exit fullscreen mode

With Axios, there's no need to convert JS objects or stringify, you simply pass the Axios POST request the URL and the object, and Axios will take care of everything else.

Handle Responses with Axios

When we send an HTTP request to a remote server, we receive a response from that server containing certain information. We can retrieve this response using Axios.

According to Axios documentation, the returned response contains the following information.

{
  // `data` is the response that was provided by the server
  data: {},
  // `status` is the HTTP status code from the server response
  status: 200,
  // `statusText` is the HTTP status message from the server response
  statusText: 'OK',
  // `headers` the HTTP headers that the server responded with
  // All header names are lower cased and can be accessed using the bracket notation.
  // Example: `response.headers['content-type']`
  headers: {},
  // `config` is the config that was provided to `axios` for the request
  config: {},
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance in the browser
  request: {}
}
Enter fullscreen mode Exit fullscreen mode

Since Axios is promise-based, the response is returned as a promise. So we need to use then() and catch() functions to retrieve the response and catch errors if there are any.

Let’s see how we can handle the response returned by a POST request.

axios.post("/users", {
    username: "sam123",
    firstname: "sam",
    lastname: "smith"
    })
    .then(response => {
        console.log(response);
        console.log(response.data);
        console.log(response.data.userId);
        console.log(response.status);
        console.log(response.statusText);
    })
    .catch(error => {
            console.log(error.message);
    });
Enter fullscreen mode Exit fullscreen mode

Use Async/Await

We can also use async/await to send HTTP requests and handle responses instead of promises.

async function getUserData() {
    try {
        const response = await axios.get("/users/sam123");
        console.log(response);
    }
    catch (error) {
        console.log(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

Working with concurrent requests

In the previous section, we used Promise.all() method to send multiple concurrent requests. When all the requests passed to the method are completed, it returns a single promise with response objects of every request. We can separate the responses using the index of each request in the array passed to the method.

Promise.all([
    axios.get("/users/sam123"),
    axios.get("/users/sam123/comments")
    ])
    .then(response => {
       const user = response[0].data
       const comments = response[1].data
    })
    .catch(error => {
        console.log(error);
    });
Enter fullscreen mode Exit fullscreen mode

Error handling with Axios and HTTP status code

If an error occurs when sending an HTTP request with Axios, the returned error object contains specific information to help us determine exactly where the error occurred.

Errors could occur in any of the following three areas:

  • The request responded with a status code out of the range of 2xx
  • Time out, the request was made, but no response was received
  • Something else blew up when setting up the request

With Axios, you can identify these different scenarios and act accordingly. Here is some example code that can help you get started

axios.get('/user?firstName=jc')
  .catch(function (error) {
    if (error.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
    } else if (error.request) {
      // Time out, the request was made, but no response was received
      // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
      // http.ClientRequest in node.js
      console.log(error.request);
    } else {
      // Something else blew up when setting up the request
      console.log('Error', error.message);
    }
    console.log(error.config);
  });
Enter fullscreen mode Exit fullscreen mode

Transform Data with Axios

We talked about how Axios will transform data automatically into and from JSON for you, but what if you require any other transformations? For example, working with some APIs is common to see attributes in snake-case (e.g., first_name). However, we don't want snake-case in our JS code. We want something like "firstName" instead.

For purposes like these, Axios provides a feature that allows you to transform requests and responses with two simple functions:

axios({
    method: "post",
    url: "users/sam123",
    data: {
        username: "sam123",
        firstname: "sam",
        lastname: "smith"
    },
    // `transformRequest` allows changes to the request data before it is sent to the server
    // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'
    // The last function in the array must return a string or an instance of Buffer, ArrayBuffer,
    // FormData or Stream
    // You may modify the headers object.
    transformRequest: [(data, headers) => {
        //Transform request data as you prefer
        return data;
    }],
    // `transformResponse` allows changes to the response data to be made before
    // it is passed to then/catch
    transformResponse: [(data) => {
        //Transform the response data as you prefer
        return data;
    }]
});
Enter fullscreen mode Exit fullscreen mode

Intercept Requests

HTTP request interception is one of the most interesting features in Axios. It allows you to intercept requests sent by and requests received by your program and carry out some common tasks before the operation is complete. This feature simplifies handling background tasks related to HTTP requests, such as logging, authentication, and authorization.

Defining an interceptor for either requests or responses is a simple task.

axios.intercept.request.use(config => {
    //Intercept the request and do something before it is sent
    console.log("Request sent");
    return config;
}, error => {
    return Promise.reject(error);
});
axios.get("/users/sam123")
    .then(response => {
        console.log(response.data);
    });
Enter fullscreen mode Exit fullscreen mode

Here, the config object is the exact config object we pass the Axios function or one of its aliases. So the interceptor has full access to the request config and its data.

After setting the request interceptor, every time a new request is sent by the program, we print the message: "Request sent" to the console.

We can similarly set a response interceptor.

axios.intercept.response.use(config => {
    //Intercept the response and do something when it is received
    console.log("Response recieved");
    return config;
}, error => {
    return Promise.reject(error);
});
axios.get("/users/sam123")
    .then(response => {
        console.log(response.data);
    });
Enter fullscreen mode Exit fullscreen mode

Every time we receive a response, we print the message: "Response received" to the console.

We can define interceptors for instances instead of the Axios object as well.

instance.intercept.request.use(config => {
    //Intercept the request and do something before it is sent
    console.log("Request sent");
    return config;
}, error => {
    return Promise.reject(error);
});
Enter fullscreen mode Exit fullscreen mode

Cancel Requests with Axios

There are some cases in web development where we might find the response from the remote server to our request is no longer important. In such cases, we can save the system resources by simply canceling the request (I know, most of the time, developers don't, but we should). And Axios provides us with a method to do just that, in a very similar way to Fetch, by using the AbortController.

const controller = new AbortController();
axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// cancel the request
controller.abort()
Enter fullscreen mode Exit fullscreen mode

You may see in some older code the use of the Axios cancel token API. However, that method has been deprecated by the more friendly and standard AbortController.


Set Custom Headers for Requests

You can easily set custom headers for the requests you are sending with Axios. You only have to pass an object containing the custom headers to the request method you are using.

const options = {
    headers: {"X-Custom-Header": "value"}
}
axios.get("users/sam123", options);
Enter fullscreen mode Exit fullscreen mode

Set Config Defaults

In a given application is common to have a base set of configurations that would apply to all web requests; it could be something like a base URL, some headers, etc. But if your application uses Axios multiple times in multiple files, it could end up being messy to repeat the same code over and over again.

That's where config defaults come in. They allow you to set default configuration options for all Axios requests.

For example, if you want to set the base URL or an authorization header for every request, it can be easily achieved, as the following example shows.

axios.defaults.baseURL = "https://example.com";
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN
Enter fullscreen mode Exit fullscreen mode

Set Config Defaults of Instances

Sometimes, setting default configurations for every HTTP request becomes unrealistic due to the differences in requests we send: we could send requests to two different APIs or with different authorization tokens depending on the user permissions.

In such cases, though we are not able to find config options common to every request, we might be able to find options common to different groups of requests. Axios provides us with a way to set default configs for these different groups separately.

It’s by creating instances.

We can create separate instances and set default configs for each instance. Then, we can use this instance object to send requests instead of the Axios object.

// Create new instance
const instance = axios.create();
// Set config defaults for the instance
instance.defaults.baseURL = "https://example.com";
instance.defaults.headers.common["Authorization"] = AUTH_TOKEN;
// Send requests using the created instance
instance.get("/users", {
    params: {
        firstname: "sam"
    }
});
Enter fullscreen mode Exit fullscreen mode

Protect against XSRF Attacks

Cross-site request forgery (XSRF) is a technique used by attackers to infiltrate web applications and carry out malicious tasks. In these attacks, the attacker disguises as a trusted user and tricks the application into executing actions for their benefit.

This could compromise the privacy and security of the user and even result in the attacker gaining access to the entire system if the user has high-level permission.

Axios provides a way to prevent such attacks by embedding additional authentication information when creating the request. This is how it is implemented.

const options = {
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',
};
axios.post("/users", options);
Enter fullscreen mode Exit fullscreen mode

Popular Axios libraries to extend its functionality

  • axios-mock-adapter: Axios adapter that allows easy mock requests
  • axios-hooks: React hooks for Axios, with built-in support for server-side rendering.
  • axios-retry: Axios plugin that intercepts failed requests and retries them whenever possible.
  • moxios: Mock Axios requests for testing
  • axios-extensions: 🍱 Axios extensions lib, including throttle, cache, retry features, etc...
  • axios-cache-adapter: Caching adapter for Axios. Store request results in a configurable store to prevent unneeded network requests.
  • axios-curlirize: Axios plugin converting requests to cURL commands, saving and logging them.

FAQs

Can I use Axios with React, Vue, or Angular?"

Yes, you can use Axios with React or any other JS framework, as Axios can run on the browser or the server.

What is the difference between Fetch API and Axios?

Axios provides more features out of the box than Fetch API; with that said, all those features have equivalents with Fetch but would require more code to get them to work. So if you don't mind installing a lightweight library to handle your requests, Axios is a great option, with more features and a very likable API.

Can I mock Axios for unit testing?"

Yes, you can write unit tests for applications using Axios, and you can mock the Axios API. Here is an example:

import axios from 'axios';
// Mock out all top level functions, such as get, put, delete and post:
jest.mock("axios");
// ...
test("good response", () => {
  axios.get.mockImplementation(() => Promise.resolve({ data: {...} }));
  // ...
});
test("bad response", () => {
  axios.get.mockImplementation(() => Promise.reject({ ... }));
  // ...
});
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we explained what Axios is and why it is a great choice for your project. We also gave examples of working with GET and POST requests and more advanced features like API intercept request, default request config, transforms, handling errors, and more.

Axios is a great library for making HTTP requests, and it provides developers with many features that can help them make the most out of their applications. We hope this article has provided enough information to use Axios in your projects.

Thanks for reading, and happy requests!


Newsletter

Subscribe to my weekly newsletter for developers and builders and get a weekly email with relevant content.

Top comments (0)