Lesson 3 - Running the project and first lines in Express
In the previous lesson, REST API, SOAP, GRAPH, and JSON, we introduced different types of web APIs. The lesson was very theoretical. Today we're going to practice and dive into the secrets of a simple RESTful API in Node.js.
In the first lesson, we created a server using the built-in http
module. Modules are a powerful weapon of Node itself. But for the start, we'll
make our work easier and go straight ahead - using the popular Express
library.
Express
Express is a popular framework for everyday work in Node.js. It's fast, minimalistic, and easy to understand. It has a very well-written documentation (which I wouldn't dare to say about Node itself). It's a tool that is supported by many other Node.js libraries, so it's worth knowing. It's unopinionated, which means that it does not try to offer any "best practices" or recommended components, but leaves it to the developer to find and use practices and components that suit them.
Thanks to Express, our code will be much shorter. Node is low-level, and if
we used the http
module directly, we'd have a lot of work to do
with parsing requests, routing using regular expressions, setting headers, and
so on. Express will help us with all this while maintaining speed and our
opinion to use it as we want.
Creating the project
Because sooner or later our code starts growing, it's time to start
organizing it somehow. As in the first lesson, we'll work from the terminal
using the IDE or from the command line. Create a new directory and enter it.
We'll use the npm package system (see the first lesson again). We need to create
a package.json
file to initialize it.
package.json
contains basic information about the project, the
author's name, description, version, git repository link, dependency list, or
command-line scripts to run the project. To create it, we'll enter this to the
command line:
npm init
Now let's answer all the questions one by one. (You can accept the offered
answers and just answer with the Enter key.) Once it's done, the
package.json
file should be created in the project directory, where
you can see the data you entered during the initialization.
If you want to do things faster, you can run
npm init
with the --yes
parameter, which will answer
"yes" to all the questions for you.
If we created the folder and moved to it using the command line as well, the sequence of commands would look like this:
mkdir node-project cd node-project npm init --yes
Installing Express
We'll use the npm package system again to install Express. Run this command from your command line:
npm install express
And in a moment, you have Express installed. For older versions of npm, we
had to provide the --save
parameter to add the package in
dependencies in the package.json
file. This parameter is no longer
needed today and the package is added to package.json
automatically.
Two things happened when installing Express. First, the
package.json
file has been changed, a new dependencies
property appeared in it, whose value is an object, and the first property of
this object is express
. The value of express
is its
version. Special characters such as the up arrow (^
) or the tilde
(~
) often appear before the version. They indicate which further
versions of the package are still supported by our project.
Specifically, the up arrow that appeared with Express means that we are happy
with any further version in which the major version number (major, the
first number before the dot) does not change, but other numbers may change. So
"^4.16.4"
means the same as "4.x"
(or, more logically,
"4.x.x"
).
Below is a sample of the package.json
file:
{ "name": "node-project", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.16.4" } }
The second this which happened is the node_modules/
directory
being created, where Express has been installed. If you look in this directory,
you'll find that not only Express, but also many other packages have been
installed as well. This is because Express depends on these packages and needs
them to work. Each of these packages (including Express) has its own
package.json
file, where you can read who the author is, what is
its version, its description, as well as the list of dependencies on other
packages.
Our first code in Express
Our environment is ready, let's finally write some code. We'll create the
index.js
file in the project root and insert the following lines
into it:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(3000, () => console.log('Listening on port 3000...'));
In the beginning, it's necessary to tell Node that we're going to use
Express. To do this, we use the require()
function. By calling it,
another function is returned, and we store it to the express
constant. We also call it immediately, and store the resulting
express
object in a constant, which according to the convention, is
named app
.
This app
object contains many useful methods. These include:
app.get()
,app.post()
,app.put()
, andapp.delete()
.
You may have noticed that these methods match the HTTP methods of the RESTful API. Today we're going to focus on the GET method. Next time, we'll focus on the others.
We pass two parameters to the app.get()
method. The first is the
path, and the second is the callback function (callback). It takes two
parameters, the request and our response to it. And we use
response.send()
to show the answer.
To listen on the selected port, we use the app
object's method
again, namely app.listen()
. Its parameters are self-explanatory (a
port number and a callback function that will be called when the application
starts listening on this port number).
Note: We use the ES6 syntax here freely. We know the environment our code will run in (that's our server), so we don't have to worry about archaic browsers, and we can feel free to us it. For those of you who don't know ES6, see the note at the end of the article for a quick explanation.
Now we can start our application from the command line:
node index.js
And type http://localhost:3000/
in our browser's address
bar:
Returning Static Data
That's all nice, you think. But we wrote the same in the first lesson, maybe even less, and we didn't even need Express for that. So when do we finally start doing something extra?
The answer is: Now
We'll call app.get()
again, this time with different
parameters:
app.get('/api', (req, res) => { res.send([10, 20, 30]); });
(just add the code to your original code in
index.js
)
Now, for requests with the /api
path, we return a three-element
array (we could return anything, the array is for illustration only). Restart
the application (usually Ctrl + C on Windows,
Cmd + C on Mac and run node index.js
again).
If you type localhost:3000/api
in your browser's address bar, that
array will appear. If you delete api
from the path, the application
will return what it originally returned.
API Response to Parameters
And what about finally trying something interesting? We could create an application that takes a bit of the path from the address bar and writes it backwards. The following code will do the trick:
app.get('/reverse/:text', (req, res) => { res.send([...req.params.text].reverse().join('')); });
We use the colon in :parameter_name
to define a parameter that
can be later found in req.params
. Then the entire call will be
req.params.parameter-name
.
The reverse()
and join()
methods are basic
JavaScript methods and can be found in the documentation. If the three dots
caught your eye, it's the spread operator, one of the new features of ES6.
After adding the code, restart the application. Now we can type
localhost:3000/reverse/reverse-this-text-please
in the address
bar:
Next time, in the lesson Complete RESTful API in Node.js, we'll talk about how we can use other RESTful API methods in Express. We'll also show what we can do to not have to restart our app all the time.
Final note: ES6 syntax used
If you don't know ES6, let me quickly explain what we use from it:
const
(similar tolet
) is a new keyword in ES6. Unlikevar
, it specifies variables (let
) and constants (const
) whose scope is not limited to the wrapping function but to the wrapping block. The block is defined by braces{}
.- Spread operator (three dots
...
) can split arrays into elements. Here it's used to split a string into individual characters (which are then added into an array). - Then an arrow function is used:
(req, res) => console.log("Hello World!");
It's again syntax from ES6, approximately equivalent to the following code:
function(req, res) { console.log("Hello World!"); };
Arrow functions differ from normal functions mainly in the way they set
the context of the function that the this
keyword works with. For a
more detailed explanation, I'd rather refer to the local JavaScript OOP course.