REST API with Express.js
Node.js

Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Before Node.js JavaScript was only used in the client-side, but now with Node.js it is possible to use JavaScript also in the server-side. You can download Node.js from the page https://nodejs.org/en/.

As an asynchronous event driven JavaScript runtime, Node is designed to build scalable network applications.

Example make a folder and add a file named server.js inside that folder. Then add below code to the server.js file

  const http = require('http');

  const hostname = '127.0.0.1';
  const port = 3000;

  const server = http.createServer(
      function (request, response) {
          res.statusCode = 200;
          res.setHeader('Content-Type', 'text/plain');
          res.end('Hello World\n');
      }
  );

  server.listen(port, hostname, 
      function() {
          console.log(`Server running at http://${hostname}:${port}/`);
      }
  );
  
Then inside the folder give a command node server.js and then with your browser navigate to url localhost:3000. So now you have a simple "web-server".

If you just close the terminal, the server is still running and you can not restart it. In this case, you can shut the server like this

    Open Terminal and execute command 
    netstat -ano | find "3000"

    Check The PID number and execute command 
    taskkill /F /PID number
  

Note! You can stop the server byt pressing CTRL+C, in the terminal.

npm

npm is a package manager for the JavaScript programming language. It is the default package manager for the JavaScript runtime environment Node.js. When you install Node.js you will get also npm.

You can manage locally installed npm packages with the package.json file.

Example
Create a folder named test and inside that folder give a command npm init and if you just press ENTER to all questions, you will have below package.json file

    {
      "name": "test",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
  
Then if you example would like to use MySQL in your application, you can add below lines to package.json
    "dependencies": {
        "mysql2": "^3.6.2"
    }
  
Then you have to execute command npm install. Now npm reads the package.json file and installs all the packages which are mentioned in the file.

Instead of writing to the the package.json file, you can also execute command npm install mysql2. Now npm installs the package and writes also the needed lines to package.json.

Volta

Volta is a tool which you can use to manage JavaScript command-line tools like node and npm. You can download it from https://volta.sh/.

You can install several versions of node.js and here are some examples about the commands

  1. volta install node@lts # install latest lts version
  2. volta install node@16.9.0 # install specific version 16.9.0
  3. volta install node@12 # install the latest v12 release
And you can check which versions you have installed with the command
volta list node

If you want to set your project to use a node version which is not your default, you can set it by executing below command inside your project folder
volta pin node@16.14.0 (version 16.14.0 is just an example)

Express.js

Express.js is a backend web application framework for Node.js that dramatically simplifies server-side development.

Why use Express instead of plain Node.js?
Looking back at the basic Node.js server example earlier, even creating a simple response requires manual header setting and basic HTTP handling. Express eliminates this boilerplate by providing:

  • Easy Routing: Handle different URLs and HTTP methods (GET, POST, etc.) with simple, readable syntax instead of complex if-else chains
  • Middleware: Add functionality like JSON parsing, authentication, logging, and error handling with pre-built modules
  • Less Code: Accomplish the same tasks with significantly less code, making applications easier to develop and maintain
  • Rich Ecosystem: Access thousands of community middleware packages for common web development tasks
Express lets you focus on your application logic rather than low-level HTTP details.

You can read the basic things about Express from this webpage https://www.freecodecamp.org/news/express-explained-with-examples-installation-routing-middleware-and-more/

And you can read about middlewares from this page https://expressjs.com/en/guide/writing-middleware.html

Routing

Routing refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on)

First, you need to initialize Express application. The function express() creates a new Express application and returns it. Here is a complete basic example:

const express = require('express');
const app = express();

app.get('/',
    function(request, response){
        response.send('Hello World');
    }
);

app.listen(3000,
    function() {
        console.log('Server running on port 3000');
    }
);
Now you can run this with node filename.js and navigate to localhost:3000. Compare this to the earlier Node.js http server example - Express makes it much simpler!

Here is an example about a route for GET method

app.get('/example',
    function(request,response){
        response.send('I am example');
        console.log('I am example');
    }
);
The first parameter (/example) is the route and the function is the callback. And the url might be something like http://localhost:3000/example. If you add parameters after the route like this
app.get('/example/:name',
    function(request,response){
        response.send('Hello '+request.params.name);
    }
);
Then you have to send the request like this http://localhost:3000/example/Jim

And if you need to use two parameters in GET-request, you can use this syntax

app.get('/example2/:firstName/:lastName',
    function(request, response){
        response.send('Hello '+request.params.firstName+" "+request.params.lastName);
    }
);
Then you can send the request like this http://localhost:3000/example2/Jim/Jones

And also you can use below syntax for two parameters GET-request
app.get('/example2/:firstName&:lastName',
    function(request, response){
       response.send('Hello '+request.params.firstName+" "+request.params.lastName);
    }
);
Then you can send the request like this http://localhost:3000/example2/Jim&Jones

Here is an example about route for POST method

app.post('/',
    function(request,response){
        response.send(request.body);
        console.log(request.body);
    }
);
Above function will response with the same data that you send inside the HTTP body.

Note: In this website's example application, we use a more modular routing structure with express.Router(). This allows you to organize routes into separate files and modules. For example:

const express = require('express');
const router = express.Router();

router.get('/books',
    function(request, response){
        response.send('List of books');
    }
);

router.post('/books',
    function(request, response){
        response.send('Add a new book');
    }
);

module.exports = router;
Then in your main application file (e.g., server.js or app.js), you import and use this router:
const express = require('express');
const app = express();
const bookRouter = require('./routes/books');

app.use('/api', bookRouter);

app.listen(3000);
This structure makes the application more organized and maintainable, especially when you have many routes. The routes defined in the router will be accessed at /api/books (combining the base path from app.use and the route path).

Middleware

Middleware functions are executed for every incoming request and run before reaching the route handlers written after the middleware. Below is an example about middleware function

app.use(
    function(req,res,next){
        console.log('The common middleware called');
        next();
    }
);
So, above middleware is executed after every request to every routes (written after the middleware). You can also add a path to the middleware.
app.use('/example',
    function(req,res,next){
        console.log('The example middleware called');
        next();
    }
);
So, the above middleware is executed after any incoming request's, where path starts with /example — regardless of the method (GET, POST, etc.).

The next function is a function in the Express router which is used to execute the other middleware functions succeeding the current middleware.

Express with MySQL

This section demonstrates how to integrate MySQL database with Express applications using callback-based approach. Understanding callbacks is fundamental to asynchronous programming in Node.js, and provides the foundation for learning more advanced patterns like async/await later.

In this example we will use MySQL and we can create a file named database.js with below code

const mysql = require('mysql2');
const connection = mysql.createPool({
  host: 'localhost',
  user: 'netuser',
  password: 'netpass',
  database: 'netdb'
});
module.exports = connection;

Here is an example about endpoint which will return the name of a book based on the id given in the htpp-request.

const db = require('../database');

app.get('/book/:id',
 function(request, response) {
  db.query('select name from book where id_book=?', [request.params.id], 
    function (err, dbResult){
      if (err) {
        response.json(err);
      } else {
        response.json(dbResult);
      }
    })
 }
);
In above code we created an object named db, which we can use for the queries.

Here is the same example, where the database query is separated to it's own function named getById

const db = require('../database');

app.get('/book/:id',
 function(request, response) {
    getById(request.params.id, 
      function(err, result) {
        if (err) {
          response.json(err);
        } else {
          response.json(result);
        }
      })
 }
);

const getById = function(idFromRequest, callback) {
  return db.query('select name from book where id_book=?', [idFromRequest], callback);
}
The function getById has two parameters: idFromRequest and callback.
  • request.params.id, this will be the idFromRequest in getById
  • the anonymous function, this will be callback in getById
query is a method of mysql2-module, which can take 2 arguments
  1. SQL-code
  2. function which will be called (callback) after the query is ready
And the callback function can take 3 parameters, like this
function(err, result, fields)
Explanation for above parameters:
  • err – Contains an error object if something goes wrong during the query (e.g. syntax error, connection issue). It's null if the query is successful.
  • result – The actual data returned from the query. For example, an array of objects representing the rows from the result set.
  • fields – Metadata about the columns in the result set, such as column names, data types, and table names.
So, after the query is ready the results will be saved to the variable result.

In the following line of code:

return db.query('SELECT name FROM book WHERE id_book = ?', [idFromRequest], callback);

Explanation:

  • ? — This is a placeholder for a value in a prepared SQL statement. It tells the database engine to safely insert a value here without risking SQL injection.
  • [] — This is an array of values that will replace the placeholders in the query. Each value in the array corresponds to a ? in the SQL string, in order.

For example, if idFromRequest is 5, the query becomes:

SELECT name FROM book WHERE id_book = 5

This substitution is handled safely by the database driver, preventing SQL injection and automatically escaping values.

You can read more details about the node.js driver for mysql2 from https://www.npmjs.com/package/mysql2

Response format

You can choose to send the response as a JSON array or as a JSON object or as a string.

Example you have made this kind of SQL-query
select CONCAT(fname," ",lname) AS fullname from person where id_person=6.
Then you can choose which kind of response to send.

response.json(dbResult);

Then the response is a JSON array like this:
[
    {
        "fullname": "Jim Smith"
    }
]
response.json(dbResult[0]);

Then the response is a JSON object like this:

{
    "fullname": "Jim Smith"
}
response.json(dbResult[0].fullname);

Then the response is a string like this:

"Jim Smith"
response.send(dbResult[0].fullname);

Then the response is a string like this:

Jim Smith



Toggle Menu