This post is a response to a frequent question from students of our REST API development course.

There we teach how to create REST APIs using Python, but we don't teach how to consume them. Usually you'll be creating a REST API to standardise and share access to resources, such as a database. For example you might want to allow both a mobile app and a web app to access your database via a REST API.

In order to do that of course, you need to know how to use your REST API from within your mobile app or web app!

In this post we'll look at how to interact with a REST API using JavaScript, so that your web apps to use it.

If you want to follow along, here's a GitHub repository with a sample Flask app and all the JavaScript examples covered in this blog post.

What "to interact" means

In the context of REST APIs, "to interact" means to make a request to the API and to get a response back.

So, how can we make requests to a REST API using JavaScript?

There are a few ways to do it.

Make HTTP requests with vanilla JavaScript

The way to make HTTP requests with JavaScript without any libraries requires a lot of typing, so normally you won't use this method. However, it's still good to know about it anyway!

Here's how you could perform a GET request using vanilla (plain) JavaScript:

const request = new XMLHttpRequest();
const url = 'http://localhost:5000/movies';
request.open("GET", url);
request.send();

request.onload = (e) => {
    alert(request.response);
}

Here we're first creating a new XMLHttpRequest. This is what holds the data for the HTTP request we're making, and then sends it off to the API (which I'm running locally, and hence the url is in localhost).

Then we open the request, passing the method and URL, here the method is "GET", as often used when retrieving data from an API.

XMLHttpRequest is asynchronous, which means that running .send() doesn't block your application until a response is received. Instead, receiving and dealing with the response can be done with one of the event handlers.

That's what .onload is for. Define a function as a value for that property, and it will run when the response arrives.

Sending form data with vanilla JavaScript

There are two main ways to send form data: using HTML and using JavaScript.

If you can, sending form data with HTML is going to be much simpler. In order to do that, you'll need to have an HTML page that contains a form and a submit button. HTML then builds out the request and sends it for you when you press the submit button.

Something like this:

<!DOCTYPE html>
<html>
    <head>

    </head>
    <body>
        <form action="http://localhost:5000" method="POST">
            <label>
                Title: <input type="text" name="title" placeholder="Movie name" />
            </label>
            <label>
                Year: <input type="text" name="year" placeholder="1994" />
            </label>
            <input type="submit" value="Submit" />
        </form>
    </body>
</html>

Note that this does not use JavaScript at all. But you could do, if you wanted the sending code to be in your JavaScript and not using HTML.

You could do this, using XMLHttpRequest:

const formData = new FormData();

formData.append("title", "The Matrix");
formData.append("year", "1999");

const response = new XMLHttpRequest();
response.open("POST", "http://localhost:5000/");
response.send(formData);

response.onload = (e) => {
    alert(response.response);
}

This looks similar to what we had before, but now we're creating a FormData object first, and appending to it the fields we want.

Then when we .open(), we say the method is "POST". That's what our sample API expects when receiving data, but it may differ in your APIs.

Finally when doing .send(), make sure to include the form data there so it gets sent to the API.

Sending JSON data with vanilla JavaScript

Sending JSON data just means sending a string, and telling the API what the string represents.

So in this example we're going to send the string containing the JSON object, and also a header telling the API that our data is JSON data.

const response = new XMLHttpRequest();

const json = JSON.stringify({
    title: "The Matrix",
    year: "1999"
});

response.open("POST", 'http://localhost:5000/')
response.setRequestHeader('Content-Type', 'application/json');

response.send(json);

response.onload = (e) => {
    alert(response.response);
}

The header we need to set is Content-Type, and the value is application/json. That takes care of our API knowing that it's receiving JSON data.

The data we're using in .send() though, cannot be a JavaScript Object. It must be a string—you can turn JavaScript Objects into strings by doing JSON.stringify().

Getting data with JavaScript's fetch

Newer versions of JavaScript (called ES6) come with a function, called fetch(), which greatly simplifies and improves on the traditional way of sending and receiving requests and responses.

To retrieve data using fetch() instead of XMLHttpRequest, you'll have to do something like this. Do make sure that the browser running this code supports ES6. Chrome is a good option.

const url = 'http://localhost:5000/movies';
fetch(url)
.then(data => data.json())
.then((json) => {
    alert(JSON.stringify(json));
})

If you're not sure whether your user's browsers will support fetch(), normally what we do is we turn this modern JavaScript code into older code by using a tool called a transpiler.

In that code, we use the .then() syntax for Promises in ES6 to tell JavaScript what to do when a response arrives, rather than using event handlers.

This is cleaner and keeps the code related to response handling in the same place as the code for making the request.

Sending JSON with JavaScript's fetch

Sending data with fetch() might also seem quite verbose—just as much as using XMLHttpRequest, but I think it's a bit more readable when you know what it means!

Take a look at this:

const url = 'http://localhost:5000/';
const data = { title: "The Matrix", year: "1994" };

fetch(
    url,
    {
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
        method: "POST"
    }
)
.then(data => data.json())
.then((json) => {
    alert(JSON.stringify(json));
});

The main part of this code is that we're calling fetch() with two arguments: url and options.

The options include headers, body, and method. This contains everything that our request needs in order to be sent successfully.

Because all the options are in one place, I think it's more readable than the XMLHttpRequest counterpart.

Conclusion

There are many more libraries that can be used to send HTTP requests with JavaScript, like jQuery, axios, Angular's HttpClient, and more. However, I would stick to fetch() wherever possible, as that is the new, modern, recommended approach.

Thank you for reading today's blog post, I hope it'll be useful in your REST API development!

If you want to learn how to create REST APIs, please check out our REST APIs with Flask and Python course. Also, sign up to our mailing list as we share discount codes with our subscribers each month!

See you next time!