Previously, we've seen how to structure our API requests and make our API requests from Postman and also
from the browser,
but what if we want to create an app where we need our server to make the API requests?
This is one of the most common needs when we're dealing with Node and Express backends.
So let's see how we can do this using native Node and Axios.
This is essentially what we're trying to do.
We're trying to get our server to make a request to somebody else's server and they in return will send
us a response with the data or resource that we need and we can do that through their public API.
Now the code for this would look quite long and complicated if we're using native node modules such
as the HTTPS module. So we can use HTTPS to essentially make this request from our server, to reach out
from our server to the API provider's server.
Let's run through this code line by line so that we can understand it first.
The first thing we set are a bunch of options, including the base URL for where the API is hosted.
Then we have our path, which is our endpoint that we're trying to tap into.
And finally we provide a method for how we want to interact with that API.
Now the next thing we do is we put these options into a request method from this https module.
And as I mentioned before, this is something that you don't have to install,
it comes pre-built with Node. As you can imagine, needing to reach out from a server to another resource
on the internet is a relatively common need.
The response comes back in the form of a callback and it comes back in packets.
So we need to group those packets together and add each chunk onto a data string.
Once we receive the "end" message from our request, that means all the chunks have been sent over and
we can now use the data that we've collected.
We use our JSON.parse to turn that string data, that JSON format data into a JavaScript object which
we store under a variable, and then we can pass that over to our front-end using EJS or whichever means
we want.
And we also have this "try catch block" so that if there were any errors, we can send an error message
to the user or at least handle it on our back-end.
Finally, you have also a possible error message that can come from this request.
And if we do receive that message, then we have a callback to handle this particular error as well.
And finally, we end the request.
We tell it that we're done and we close that access portal to the outside.
As you can see, it's quite involved.
There's a lot of lines of code and while it is relatively doable, I recommend instead of using the
native Node module, to use something called Axios.
What Axios is able to do is it knows what is the purpose we're trying to achieve.
We're trying to reach out from our server to another resource on the Internet
and it makes these responses very simple.
In the same way that Express makes creating our server using Node a lot simpler by simplifying a lot
of the commonly used methods and requirements,
Axios does pretty much the same thing.
Instead of all of that code that you saw earlier on, we pretty much just have these five lines of code
to sort all of that out.
So we're using the Axios package from NPM and we're using the GET method to make a request to a particular
API with an endpoint,
just as you would type this into the browser, you can put this into the GET method. And this is something
that is promise based,
so we can either use .then or we can use async await in order to handle the response.
In our case, because what we're trying to do here is we're trying to render a home page and we want
to provide it with some activity data we can use, await to actually wait for this to finish and then
go ahead and res.render the index page.
Now notice another feature about Axios,
when we get JSON data back, we can simply tap into it and it can automatically turn it into a JavaScript
object without needing to add an extra step and use JSON.parse.
Axios also has much better error handling.
It makes it a lot easier to group errors together and handle them in one place in your server,
but the main reason why we want to use it is because making the requests from our server to another
server is simplified down to pretty much just one line.
Again, comparing these two versions doing pretty much the same thing, we can see that all of this
is pretty much simplified into this one line.
If you want to check it out, head over to NPM and find the Axios package.
And as always as a proxy, always look at the weekly downloads to see how popular this is,
and as you can see, it's got 44 million weekly downloads.
It's almost on par with Express and all of the other popular packages.
Professional developers use Axios a lot for the purposes that we've just talked about and also others.
And as I say, we don't always have to reinvent the wheel.
We can actually leverage other people's work and make our lives a lot easier.
So as I mentioned, Axios makes an alias for all of the most commonly used request methods.
So we saw just now axios.get, they've got delete, post, put, patch and pretty much all the things
that you will need on a regular basis when you're making requests from your Express server.
Let's try it out in practice.
Let's put our knowledge to the test and if you go ahead and download 5.3 Axios.zip, extract the folder
and open it inside VS Code, you'll see that I've prepared a file within index.ejs and index.js.
If we take a look at the packages that have been added as dependencies, we've got Axios, body-parser,
EJS and Express.
Before you do anything, go ahead and "npm install" all of those packages.
And once you've done that, I want you to go ahead and use Nodemon to run the solution.js.
As always, don't peek, don't cheat, let's run the solution file and see what it is that we're
trying to create.
This is the website we're creating.
It's a website called, "I'm Bored" and it's going to help you find something to do when you're bored.
When you first load up the homepage, when you make the first GET request, it's going to fetch a random
activity from that endpoint which was bored-api.appbrewery.com/random.
So this is just a random activity that gets populated into this card.
You can see it's got the name of the activity, it's got the type of activity and also the number of
participants in this card.
Another thing that you can do with this website hitting up a different route on our server is to make
a POST request and say, "I want to find activities that have a type of education that are for a single
person to do."
So let's hit Go, and it's going to find an educational type
and with the number of matching participants that you requested and it gives you a card back.
Now, there are cases where this fails.
So for example, in our bored API, there actually are no educational-type activities that are for two
people.
So if you hit Go in this case, you'll get an error back and we handle that error and pass a relevant
message for the user.
So in this case, it says. "No activities that match your criteria."
That's pretty much the entire website.
Let's take a look what it takes to make this work.
As you see, we've already got some starting code for you in the index.js,
and after you've installed your node_modules, the first step is to make the GET route for the home
page work.
When the user visits the homepage, it should show a single random activity.
I've already included the code that we showed you earlier on in the slide deck.
This is how you make a GET request with Axios, passing in the full URL of your request, you get back
the result in the form of response.data and you can actually log this just to see what is the structure
of the data you get back in the form of a JSON.
Alternatively, you can do it in your browser or you can do it in Postman as we have been doing before.
Once you're familiar with the structure of the data, then we can pass it over to the index.ejs file
and we can take that data object over here and populate the various parts of our website.
So we should be able to show the activity, show the type, show the number of participants.
You can either comment out this error part or you can simply handle it,
and if there were any errors, we want to show this particular div.
The second step is to make the POST route work and the POST route is tied to this form up here. So
it makes a post request to the root route,
and there are two dropdown lists.
One has the name of "type" and it has various values depending on what the user picked from the dropdown,
and the second one has the name of participants and again, has a number of options as well.
When the user submits, it's going to hit up this POST route right here in our server and we're going
to console.log() the req.body so that we're familiar with what it is we can get access to through
the req.body.
Once you're familiar with that, then you can play around with structuring the API requests, using
Axios and also using what you know about how to structure API requests that have queries that need to
be parsed.
Make sure that you're hitting up the /filter endpoint and you're passing in both of the queries, type
and participant.
And then once you're done, go ahead and take that data and render the index.ejs with a single random
activity that comes back from the request.
This is important because, as you know, when we filter on the activities, we get back an array.
So we have lots of different options
sometimes,
sometimes we have a few options,
but I want you to take a random activity from the array and then pass it to the Index.ejs.
We only ever want to display a single activity here.
Finally, once you've done that process, any errors that you get from this stage. Now, when you get an
error and you can log that error and if the error actually is a 404 error, you'll know from previous
lessons,
that means that, "the resource is not found."
And what this means is that if we try to filter on our API and find an activity with criteria that actually
doesn't fetch any resources,
we have to tell the user in this case that no activities were found that match your criteria.
Just as the same, when we try to check for educational activities for two people, we get a 404 request
on the API.
So it would be hitting up the filter endpoint,
the type would be equal to education, and the participants would be equal to 2.
And when I do this, you can see that we get an error back,
and also when we take a look in the console the HTTP status code is a 404 because the API does not
have anything for that resource that we requested.
There is a little bit of EJS formatting, understanding JSON structure, there is a little bit of Axios making
server-side requests and also there's a little bit of error handling in this challenge.
So I'm going to let you pause the video and let you get on with the challenge.
Give it a go now.
All right, let's run through the solution together.
So the first step is to hit up the index.ejs file.
And if we take a look inside the solution.ejs, you can see what I'm doing here is checking to see
if there was any data being passed over through the locals.data property,
and if there were, then I will show the data.activity, data.type and data.participants
into the card.
If there were any errors then I'm going to show this div and put the error into the div.
The next step is to structure the POST request.
And again, we're using exactly the same structure as you saw in the GET request,
we're making an async callback in this GET request, and that is because we want to wait on this GET request.
When we hit up the POST route, it's because a form was submitted from the front-end that hits up the
forward slash ("/"), the root route.
It's a POST request and we get sent over two pieces of data.
The type of activity that was selected, which can have any of these values and can also be empty
or the participants property which can have any of these values.
Our job is to grab hold of those pieces of data from the request,
so req.body.type and req.body.participants, and then we insert it into our
URL.
As you've seen before, this is how we can structure our API requests by adding a query, type="
whatever the user submitted" and participants = "whatever the user submitted".
Now, remember that with the API requests where these queries are optional as in the case of our bored API,
remember that these queries can actually be empty as it describes in the documentation,
what that means is if the user selected the random type or any number of people, the value we get back
from that request is an empty string.
So then type equals an empty string, participants equals an empty string,
and that means that we're making those two filters optional.
So it will come back with all of the activities essentially.
So then we use Axios to make this GET request.
We reach from our server into the bored API server.
We get back some response. data in the format of a JavaScript object.
Ideally, you might want to log that just to check and make sure it is in fact a JavaScript object and
how it is structured.
And then we use that data to render our home page passing over a random item from the result.
So remember, as I said, you get an array back, an array of activities, but we only want to display
a single activity here so we can fetch a random one from the array.
And then finally we do a little bit of error handling to make sure that if we caught an error in this
request, we're trying to get some resource from the filter endpoint passing in some queries,
then in all likelihood it's because there were no activities that match our criteria.
And you can also console.log() the error message when that happens
just to check as well.
You could make this error handling even more specific.
You could say that when the error that comes back is a 404, then we say that, "No activities match your
criteria."
If it was a different error message, maybe, "There's a network error," or "The internet is down," then we
pass a different message.
This is probably the simplest way to handle it, but it is up to you how you want to do it.
And so there you have it.
That is a very simple website that we've built with Node Express and Axios to make API requests from
a third-party public API.