Learning while teaching — Class 4
Hey guys, welcome back, hope you are enjoying the classes so far!
Any doubts in the last 3 classes? If so, leave me a comment or send me an email at firstname.lastname@example.org.
Today we are going to start the project that we should finish (hopefully) by the end of all these classes. I’ll try to make this project at least useful for some of you and introduce some concepts which might be really useful in real world applications.
For today’s class we will understand what an REST API is and how to create and test (manual testing) it!
Code? Code? Code?
Well, by this point you should already know! But if you don’t, here is it: https://github.com/lucavgobbi/lwt-project
Guess what? These two beautiful words have a meaning! They stand for Representational state transfer application programming interface. Great uhh? But let’s be honest, right now it doesn’t mean anything for us.
Instead of decrypting what this name means let’s try to understand the concept behind it!
API is a word that you will hear all the time after you start your life as a programmer. In a broad way, an API is how we interact with other software, platform or code. APIs provide us methods to use other applications, for instance, your app wants to access Facebook data and Facebook will not give you access to their code, servers or database but they might give you a public API which let you access some of their data. Packages have APIs, when you are using the methods provided by Express.js to create your application you are using their API! You don’t have to dig into their code to do it, you just need to make calls to their API.
The great thing about APIs is that they (supposedly) abstract a lot of complication for us. Let’s say that you want to use an given API to create a new user. When you call the API we expect it to validate the data like if the user doesn’t exist in the system or if all the required information was provided. API should also make business logic simple, for instance, when using a budget system API if we want to add a new expense to our account the API method could calculate automatically the new account balance!
These are only some really basic examples but the key point is: APIs should help developers access other systems or resources without having to understand deeply how they were implemented, and to make this possible APIs should be consistent which means, behave in an expected way and be well documented!
Now let’s setup our app. All steps below were already explained in earlier classes, so I will just write them with no further explanation. If you have any doubts go back to previous classes or email me :).
- Create the directory, go inside it
- Assuming that NPM and Node are installed (Class 2)
3. Assuming that express-generator is already installed (Class 3), run
This will install all the dependencies required for our first step application and create the boilerplate of our application.
Great, so now we have a lot of directories and some files, what should we do now?
Express.js is route based framework, in other words this means that when someone request a document from your server he is not accessing a real directory to get it, instead, Express will match the URL with a route and execute some code to create the response. So let’s start by looking the routes which were provided by express-generator.
Open the app.js file in your root directory. You should see these two lines:
You might remember middlewares right? Also you should remember that by Express.js owns definition:
Express is a routing and middleware web framework with minimal functionality of its own: An Express application is essentially a series of middleware calls.
The same method .use() from app is used, but pay attention to a simple detail, instead of receiving one parameter, this method is receiving two! The first parameter is the path where this middleware will be attached, So in this case when someone requests document in the ‘/’ path of our server the request will be “delegated” to routes. But what is routes? Well, just check the code, remember, routes is an object, is might be defined somewhere!
var routes = require('./routes/index');
var users = require('./routes/users');
Now, looking in the beginning of the code can found where routes and users are declared. Both are a .require() of a file. Just go into “routes” directory and look for two files: “index.js” and “users.js”, the .require() is referencing these two files.
For now let’s understand what is “index.js” is doing:
The line 1 is just requiring the Express.js module, that was easy.
Now the second line is different, it uses the express object required on line 1 and invoke a method called .Router() this method will return a new Router object provided by Express. You can find more information here if you want.
On the 5th line is where we start to define our routes. Remember the HTTP verbs or methods? Well, the router object has a method for each one of them! You can find .get(); .post(); .put();… and the list goes on. In this case .get() is the one being used, and if you look closer, the parameters are pretty similar to how we attach middlewares! The first defines what is the path or the route if you prefer to call it that way. The second one is the callback function which will be called if the requested URL matches to the path combination.
Paths or Routes
So let’s take a minute to understand the paths: first we created a router middleware using .use() with a ‘/’ path, inside the router we have a .get() with path also set to ‘/’. This means that any GET request for our root directory will call the callback function defined on .get().
Suppose that our server address is http://mysite.com, if I call this address (spoiler: don’t click the link, it not our site) the callback defined in the lines above will be executed. Now let’s say that we want to add another route, maybe http://mysite.com/contact. There are several ways to do so, but we will focus on two ways here:
- Adding a path to an existing route middleware
- Creating a new routing middleware
Why these two ways? Well, these are the most organized ways to do it, remember that your code will be read by other people, so keep it clean and organized!
Adding a path to an existing route middleware
We already have a route middleware, let’s add some more interesting routes to it:
We have added two new routes on our index.js route middleware. The first one on line 7, responds to a get at ‘/contact’, but differently from the first route on line 3 where the response is a view (more about it in the future) we here answer with a json.
So, on the object res which is the second parameter of our route we use the method .status() to set the HTTP status and the method .json() to write a json document on the response. Why we do that? Well our API will receive an request and will answer with a json document!
The third route on line 11 is more interesting, you might notice that part of the path parameter has ‘:name’ or ‘:email’, this tells Express that instead of expecting a fixed value it can have any value for this part of the path and this value should be assigned to name and email variables. So, for instance, if we call from our browser the URL /email@example.com the route will be mapped to /contact/:name/:email and ‘lucavgobbi’ will be available on name variable and firstname.lastname@example.org will be available on email variable. How do I access this values? Well, Express will not just inject this variables in our code, instead they will be available as part of the request object which is the req object! req has another object inside it: .params which will contains all parameters mapped on your path.
So in line 12 and 13 we access these values with req.params.name and req.params.email! Pretty simple right? And just like on the previous route we create a json response with .json() but now instead of using fixed strings, we use these values!
So let’s try it out!
Run your app, if don’t know how to do it, check class 3.
Try out in your browser the following urls:
Creating a new routing middleware
First, create a file called products.js inside routes directory.
This file will be our new route middleware and we will create new routes inside it.
At this point this code should be nothing new to you right? But just in case, it is creating a route at path ‘/’ and the function which handles this route basically create an array and use .json() to send the array as json in the response.
But this route middleware is not attached yet, so let’s do it! Back to your app.js file we need to require our new route middleware. You already know how to do it! Just user .require().
var products = require('./routes/users');
Leave this line of code near the other requires so your code will remain organized!
Ok, now we have our middleware inside a variable, but we still need to tell Express app to use it. We need to use .use() to tell Express that this middleware is part of our flow, to do so just add this code near the other routes definitions and remember, ORDER MATTERS, leave this route as the last one:
This line of code is telling express that every request which contains ‘/products’ should be handled by the products object which is our router middleware. This means that when we call http://website.com/products our router middleware will deal with this code and based on the routes defined on it will give or not a response.
Time to test it
Why not test it again? Run the app, go to your browser and go to:
What do you see?
The next parameter
You might recall from last class that middlewares required us to call next() in order to continue execution right? When building routes, we usually don’t use it. The .json() and .send() are the last methods that we should call because they send the HTTP response to the client, so everything that you do after it might be useless from the client point of view.
Right now you should have a better understanding what an API is and why they are so popular around the web, you might also be able to create a simple API using Node + Express. My advice is try to create new routes, play around with them, understand what is possible and what you can do with these simple parameters that we learned how to use today!
If you have any doubts or just want to give me a feedback: email@example.com or @lucavgobbi on Twitter, you can also join our Slack group, just email me asking for an invite!
If you liked this class, please like and share :) I would love to see you sharing it around Twitter.
Next class we will see other HTTP methods, understand the differences and learn how to test it.
See you next class! Bye ;)