Andrea Daly


So you want to build an API ?


Embarking on your API creation journey? You're in the right place! This guide will walk you through creating a web API using Node.js, a popular platform for this task. As someone still learning, I've simplified the process to its core, aiming to clarify the steps. The goal of this document is to share my experiences and challenges during API development. I hope it serves as a useful resource for others starting in this field. For now, we'll stick to the basics, with future updates diving deeper into topics like error handling and asynchronous services. Remember, the code provided here is not for production use - it's part of the learning process. As we proceed, the commands are for use on a Mac, you will have to adapt them for your OS. Ready to dive into API development?


Introduction to APIs


APIs, or Application Programming Interfaces, are a set of rules and protocols for building and interacting with software applications. They define methods and data formats that a program can use to communicate with other programs or components. Essentially, an API is a contract between different parts of an application or even different applications themselves.

APIs are essential in modern software development because they allow different software systems to communicate and exchange data without knowing the details of how the other system works. This is particularly important in web development, where front-end and back-end code often needs to communicate over the internet.

There are many types of APIs, including REST (Representational State Transfer) APIs, SOAP (Simple Object Access Protocol) APIs, and GraphQL APIs. In this tutorial, we will focus on REST APIs, which are stateless, cacheable, and designed to work over HTTP.

To use an API, you generally need to make HTTP requests to the API's endpoints. These endpoints are URLs where the API exposes certain functionality. For example, the JokeAPI endpoint `https://jokeapi.dev/joke/Programming?type=single` returns a single programming joke.

You can use an API directly in your browser by entering the API's URL into the address bar. This is a simple and quick way to test an API and see the raw response data. For example, to get a joke from the JokeAPI, open a new tab in your web browser, type `https://jokeapi.dev/joke/Programming?type=single` into the address bar, and press Enter. Your browser will send a GET request to the JokeAPI, and the API will return a joke.


Part 1: Building a Basic Node.js Server


In this part of the tutorial, we will:

  • Create a basic Node.js server that listens on port 8000 for HTTP calls.
  • Demonstrate the response via the browser URL.
  • Show how it can be accessed from JavaScript within a simple web page.

01

Set Up

  1. Install Xcode Command Line Tools: The easiest way to install them is to run the following command in the terminal:

  2. xcode-select --install
  3. Install Homebrew: Homebrew is a package manager for macOS that allows you to easily install and manage software packages. To install Homebrew, run the following command in the terminal:

  4. /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  5. Install Git: Once you have installed Homebrew, you can use it to install Git by running the following command in the terminal:

  6. brew install git
  7. Check git version: Run the following command in the terminal:

  8. git --version
  9. If the git version is apple run following command to ensure that the system looks for executables installed by Homebrew:

  10. export PATH=/usr/local/bin:$PATH
  11. Create a GitLab account https://gitlab.com

  12. Install Node.js: Node.js is a JavaScript runtime that allows you to run JavaScript on the server side. To install it using Homebrew, run the following commands in the terminal:

  13. brew update
    brew install node
  14. Install Nodemon: Nodemon is a utility that monitors for changes in your Node.js application and automatically restarts the server. To install it, run the following command in the terminal:

  15. npm install -g nodemon
  16. Install MySQL: MySQL is an open-source relational database management system. To install it using Homebrew, run the following command in the terminal:

  17. brew install mysql
  18. OR Without Homebrew:

  19. Download MySQL Community Server from the official MySQL website. Choose the DMG Archive for your macOS system.Follow the instructions and set a root password for MySQL.

  20. Login mysql:

  21. mysqladmin -u {userName} password {password}
  22. OR:

  23. mysql -u root -p
  24. Install Sublime Text: Sublime Text is a popular text editor for coding. To install it, download the installer from the Sublime Text website and follow the installation instructions.

  25. Download and Install Postman Desktop App: Postman is a tool for testing APIs. To download and install it, go to the Postman website and follow the installation instructions.

  26. * you don't need to specify a directory for these installations. They will be installed globally and can be accessed from any directory on your system.

  1. You can check that Node.js and npm are installed by running the following commands in your terminal:

  2. node -v
    npm -v
  3. Create a new directory for your project and navigate into it:

  4. mkdir 1-basic-node-server
    cd 1-basic-node-server
  5. Use npm to initialize your project. This will create a package.json file with default values:

  6. npm init -y
  7. Create a new file in the same directory called basicNodeServer.js and enter the following code defined here

  8. This creates a simple HTTP server that listens for requests on port 8000 and responds with "My First node server!" and additional header info.

  9. Start the server by running the following command in your terminal:

  10. node basicNodeServer
  11. This should output "Server running at http://localhost:8000" to the console.

  12. * If you get an error 'Error: listen EADDRINUSE: address already in use ::1:8000' use the lsof and kill commands below to kill the process and retry starting the node server.

  13. Go to browser and in url bar type http://localhost:8000 and return to view the response.

  14. Create a html page called basicNodeServer.html and enter the following code defined here

  15. Open the html file created and you will review the response within the div defined in the html page.

  16. To stop the server, press ctrl+c in the terminal.

  17. ^c
  18. If you have installed nodemon you can alternatively start the server with the following command:

  19. nodemon basicNodeServer.js
  20. This will start nodemon and automatically restart the server whenever you make changes to your code so you do not have to stop/restart the server manually following changes you make.

  21. To check if there are any servers running on a specific port and kill them if necessary, use the following commands, replacing 8000 with the port number you want to check, and {PID} with the process ID of the server you want to kill:

  22. lsof -i :8000
    kill -9 {PID}

02

Basic Node Server

basicNodeServer.js

              

// 1. include dependencies and assign to variables const http = require("http"); // 2. define constants to hold the config. of where server will be bound. const host = "localhost"; const port = 8000; // 3. verify server is created by adding requestListener //function which handles the http request and http response. //request and response objects arguments hold all info const requestListener = function(req, res){ // 4. need to use CORS to allow us to access the server on our localhost if // cross origin requests or https required or other situation required res.setHeader("Access-Control-Allow-Origin", "*"); res.writeHead(200); res.end("My First node server!" + JSON.stringify(req.headers)); // 5. for more info JSON.stringify(req.headers) }; // 6. create the server passing in the requestListener const server = http.createServer(requestListener); server.listen(port, host, () => { console.log(`Server is running on http://${host}:${port}`); });

basicNodeServer.html

<html>   <head>     <title>Get From Server</title>   </head>   <body>     <div class="myDiv" id="myDivId">set the content of this div to the content that is returned by this service</div>   </body> </html> <script type="text/javascript"> let httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = function() { if (httpRequest.readyState == 4 && httpRequest.status == 200){ console.log(httpRequest.responseText); document.getElementById('myDivId').innerHTML=httpRequest.responseText; } } httpRequest.open( "GET", "http://localhost:8000", true ); httpRequest.send( null ); </script>

Introduction to Express


Congratulations on successfully building your first API! Now, let's take our Node.js API development to the next level by introducing a powerful framework known as Express.js.


Express.js is a fast, efficient, and minimalist web framework for Node.js. It simplifies the process of writing server code, allowing us to focus on the core functionality of our application. Whether you're creating a simple website or a complex web application, Express.js can streamline your development process. It handles routing, manages HTTP requests, and integrates well with various middleware and libraries. Let's explore how it can enhance our Node.js API development journey.


Notice how the code in the express server is more simplified and there is no need to reference the http modules. In Express.js, you don't need to manually import and use the http module because Express.js itself is built on top of the http module. When you create an instance of an Express application, it inherently includes everything you would normally need from the http module, including the ability to listen for connections and handle requests and responses.


This abstraction allows you to focus on defining your application's routes and middleware, rather than having to manage low-level details of the HTTP protocol. This is part of what makes Express.js a high-level framework.


Part 2: Building a Basic Express Node.js Server


In this part of the tutorial, we will :

  1. Create a basic Express Node.js server that listens on port 8000 for HTTP calls.
  2. Demonstrate the response via the browser URL.


03

Basic Express Node Server

  1. Install Node & nvm as previously described if not already installed.

  2. Create/Navigate to new server dir:

  3. mkdir 2-basic-node-express-server
    cd 2-basic-node-express-server
  4. Initialise Node on the dir : creates a package where the project files will be stored. All the modules you download will be stored in the package.

  5. npm init -y
  6. Install express using npm:

  7. npm install express
  8. Create a new javascript file in the same directory called basicExpressNodeServer.js and enter the following code defined here

  9. This creates a simple HTTP server that listens for requests on port 8000 and responds with "Hello World!"

  10. Start the server by running the following command in your terminal:

  11. node basiExpressNodeServer
  12. This should output "Example express app listening on port 8000" to the console.

  13. You will see the response "Hello World" when navigating to url http://localhost:8000 from a browser

  14. To stop the server, press ctrl+c in the terminal.

  15. ^c
  16. If you have installed nodemon you can alternatively start the server with the following command :

  17. nodemon basicExpressNodeServer.js
  18. This will start nodemon and automatically restart the server whenever you make changes to your code so you do not have to stop/restart the server manually following changes you make.

  19. To check if there are any servers running on a specific port and kill them if necessary, use the following commands, replacing 8000 with the port number you want to check, and {PID} with the process ID of the server you want to kill:

  20. lsof -i :8000
    kill -9 {PID}

basicExpressNodeServer.js

              

// 1. Include dependencies and assign to variables const express = require('express'); // 2. Define constants to hold the configuration of where server will be bound const app = express(); const port = 8000; // 3. respond with "Hello World!" whenever the app receives an HTTP GET request at the root URL app.get('/', (req, res) => { res.send('Hello World!'); }) // 4. start the server and listen for connections on the specified port. // Once the server is ready to accept connections // it logs a message to the console app.listen(port, () => { console.log(`Example express app listening on port ${port}`); })

Creating a MySQL server


Using MySQL with Node.js can provide a solid foundation for building reliable, scalable, and secure APIs. When you're building an API, you often need to perform multiple operations simultaneously, such as reading data from a database while writing to it. By using MySQL, you can ensure that your data remains consistent and accurate even under heavy load.


MySQL is a powerful, open-source relational database management system. It's highly scalable and can handle large amounts of data, making it a good choice for APIs that need to serve many users or handle large volumes of data. Using MySQL with Node.js can provide a solid foundation for building reliable, scalable, and secure APIs.


Part 3: Creating a MySql Server


In this part of the tutorial, we will :

  1. Create a basic MySQL Server
  2. Create a basic Express Node.js that connects to a MySQL server
  3. Explore a more complex application that uses the datastore to add/delete/update employee details from a website


  1. Check if MySql is installed by running these command in your terminal:

  2. mysql --version
  3. If it is installed you can check if it is running by (*remember these commands are for mac os):

  4. pgrep -a mysql
  5. Alternatively if installed by homebrew you can type:

  6. brew services list
  7. You can use the following commands to start/stop/restart:

  8. mysql.server start
    mysql.server stop
    mysql.server restart
  9. If it is not installed you can install it via instructions available here

  10. cd your-project-dir
    mkdir 3-basic-mysql-server
    cd 3-basic-mysql-server
    npm install express mysql
    npm install body-parser --save
  11. Start the mysql as above.

  12. When it is installed and running navigate to folder where installed and type:

  13. mysql -u {your-user-name} -p
  14. example if login as the root user

  15. mysql -u root -p
  16. Will be promted to enter password, enter password and return:

  17. When logged in to find out which mysql db's already installed , From sql prompt execute :

  18. SHOW DATABASES;
  19. When logged in to create a new db, From sql prompt execute :

  20. CREATE DATABASE IF NOT EXISTS mysqlDemo;
    USE mysqlDemo;
    CREATE TABLE IF NOT EXISTS users ( id int(11) NOT NULL AUTO_INCREMENT, value_id int(11) NOT NULL, value TEXT NOT NULL, timestamp timestamp DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(id), UNIQUE KEY (value_id) );
    INSERT INTO mysqlDemo.users (value_id, value) VALUES (1, 'John Doe');
    INSERT INTO mysqlDemo.users (value_id, value) VALUES (2, 'Jane Smith');
    select * from mysqlDemo.users;
  21. To log out of the db and exit from the sql prompt:

  22. exit
    cd myProjectDir
    mkdir 3-mysql-server
    cd 3-mysql-server
  23. Create a new javascript file in the same directory called basicMySqlServer.js and enter the following code defined here

  24. This creates a simple mysql server that listens for requests on port 3306 and responds with the table information and user data just created

  25. Start the server by running the following command in your terminal:

  26. node basicMySqlServer
  27. This should output "MySql Connected" to the console along with user data from the database.

  28. Alternatively, if you have installed nodemon, you can start the server with the following command:

  29. nodemon basicMySqlServer.js
  30. This will automatically restart the server whenever you make changes to your code.

  31. To check if there are any servers running on a specific port and kill them if necessary, use the following commands, replacing 8000 with the port number you want to check, and {PID} with the process ID of the server you want to kill:

  32. lsof -i :3306
    kill -9 {PID}

04

Basic MySQL Server

basicMySqlServer.js

              

// 1. Include dependencies and assign to variables const mysql = require('mysql'); // 2. Create a connection object with the necessary credentials const conn = mysql.createConnection({ host: "127.0.0.1", port: "3306", user: "root", password: "password", database: "mysqlDemo", }); // 3. Connect to the MySQL server using the connection object conn.connect((err) => { if (err) { return console.log(err.message); } console.log("MySql Connected"); }); // 4. Define a SQL query to show all tables in the current database let sql = 'SHOW TABLES'; // 5. Execute the SQL query conn.query(sql, function (error, results, fields) { if (error) throw error; console.log(results); // 5. Extract the name of the first table from the results let tableName = results[0].Tables_in_migration; console.log("table is " + tableName); // 6. Define a SQL query to select all records from the extracted table let sqlTableContent = 'SELECT * FROM ??'; // 7. Execute the SQL query conn.query(sqlTableContent, [tableName], function (error, results, fields) { if (error) throw error; console.log(results); }); });

Node.js Server with MySQL Server


Having installed MySQL and set up a demo database, we are now going to create an express node.js server that will communicate with a MySQL server that will serve data to a simple webpage. We will create a the MySQL server and the express Node.js server in the same file for simplicity, however in a production environment these components will normally be hosted in seperate files.


We will use the information we have learned thusfar to continue in our journey to see how the data from an api can be used in a web page. This will require us to learn something of http routes.


A route is a section of Express code that associates an HTTP verb (GET, POST, PUT, DELETE, etc.), a URL path/pattern, and a function that is called to handle that pattern. There are several ways to create routes. For this tutorial we're going to use the express.Router middleware as it allows us to group the route handlers for a particular part of a site together and access them using a common route-prefix.


For example, consider the following route definition:

                

const express = require('express') const app = express() app.get('/', function(req, res) { res.send('Hello Sir') })

Here, we've defined a route for the root URL (/) of our application. When a GET request is made to this URL, the application sends the response 'Hello Sir'.


Similarly, you can define routes for other HTTP verbs like POST, PUT, DELETE, etc. Each route can have one or more handler functions, which are executed when the route is matched.


Routes play a crucial role in building web applications. They allow us to define how our application should respond to various client requests, making it possible to create dynamic and interactive web pages.



Part 4: Using MySql with a Node.js Server


In this part of the tutorial, we will :

  1. Create a basic MySQL Server
  2. Create a basic Express Node.js that connects to a MySQL server
  3. Use a webpage to communicate with the Node.js server creating/retrieving/updating the db data via routing and displaying on the webpage
  4. Explore a more complex application that uses the datastore to add/delete/update employee details from a website


05

Basic MySQL Server used with Node.js

  1. Install Node & nvm as previously described if not installed already:

  2. From Steps previously make sure MySQL is installed and running on your local machine.

  3. Create/Navigate to the your Project Directory and create new server dir:

  4. mkdir node-mysql-proj
    cd node-mysql-proj
  5. Initialise Node on the dir : creates a package where the project files will be stored. All the modules you download will be stored in the package.

  6. npm init -y
  7. Create a new javascript file in the same directory called basicMySqlNodeServer.js and enter the following code defined here

  8. touch basicMySqlNodeServer.js
  9. Paste code from previous step.

  10. Esc
    :qa!
  11. This creates a simple HTTP server that listens for requests on port 8000 . It also creates the MySQL server that it will communicate with to create/update/retrieve data.

  12. Start the server by running the following command in your terminal:

  13. node basicMySqlNodeServer
  14. This should output "Server is listening on port 8000 Connected to the database on port 3306" to the console.

  15. Now if you navigate to the browser and enter the url http://localhost:8000 you should get the response "Hello from your new MySQL integrated Node.js app"

  16. To see how the node server can be utilised to not only return data but to add data to the MySQL database create an html file within the project dir called node basicMySqlNode.html

  17. Enter the following code defined here

  18. Open the web page and add user data via the provided forms and observe how when you add a user you will then be able to retrieve that user's details
  19. To stop the server, press ctrl+c in the terminal.

  20. ^c
  21. If you have installed nodemon you can alternatively start the server with the following command :

  22. nodemon basicMySqlNodeServer.js
  23. This will start nodemon and automatically restart the server whenever you make changes to your code so you do not have to stop/restart the server manually following changes you make.

  24. To check if there are any servers running on a specific port and kill them if necessary, use the following commands, replacing 8000 with the port number you want to check, and {PID} with the process ID of the server you want to kill:

  25. lsof -i :8000
    kill -9 {PID}

basicMySqlNode.html

              

<html> <head> <title>Post To And Get From Server</title> </head> <body> <p>Will retrieve values from a mySql db and create/update the db</p> <div style="border: solid 1px black; padding: 5px; margin-bottom: 5px;"> <p>The form below will post ID and Value to your server at http://localhost:8000</p> <form onsubmit="event.preventDefault();"> <table> <tr> <td>ID </td><td><input type="text" name="id_textfield"></td> </tr> <tr> <td>Value </td><td><input type="text" name="value_textfield"></td> </tr> <tr> <td></td> <td style="text-align: right;"><input type="submit" name="Post" onclick="postToServer(this.form)"></td> </tr> </table> </form> </div> <div style="border: solid 1px black; padding: 5px;"> <p>This form will send ID via a GET request to http://localhost:8000 and display the associated value below, if it exists. Otherwise we will see a "NOT FOUND" message</p> <form onsubmit="event.preventDefault();"> <table> <tr> <td>ID </td><td><input type="text" name="id_textfield">&nbsp;<input type="submit" name="Get" onclick="getFromServer(this.form)"></td> </tr> <tr> <td>Value </td><td id="returned_value_cell"></td> </tr> </table> </form> </div> </body> </html> <script type="text/javascript"> function postToServer(form){ var httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = function() { if (httpRequest.readyState == 4 && httpRequest.status == 200){ console.log("RECEIVED"); } } var params = "id=" + form.id_textfield.value + "&value=" + form.value_textfield.value; //console.log(params); alert("params are " + params); httpRequest.open("POST", "http://localhost:8000/record", true); httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); httpRequest.send(params); } function getFromServer(form){ var httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = function() { if (httpRequest.readyState == 4 && httpRequest.status == 200){ document.getElementById('returned_value_cell').innerHTML = httpRequest.responseText; } else if (httpRequest.readyState == 4 && httpRequest.status == 404){ document.getElementById('returned_value_cell').innerHTML = '<span style="color: red;">NOT FOUND</span>'; } } var params = "id=" + form.id_textfield.value; httpRequest.open("GET", "http://localhost:8000/record?" + params, true); httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); httpRequest.send(null); } </script>

06

Basic Redis Node.js Server

  1. Install Node & nvm as previously described:

  2. Install Redis using homebrew:

  3. brew install redis
  4. Start Redis if installed using brew:

  5. brew services start redis
  6. OR else:

  7. redis-server
  8. Use redis-cli to validate ok. Open other terminal and type:

  9. redis-cli
  10. then set a pair by:

  11. set name Jane
    OK //returned
  12. Retrieve the value set in the key:

  13. get name
    Jane//returned
  14. Create/Navigate to new server dir:

  15. mkdir node-redis-proj
    cd node-redis-proj
  16. Initialise Node on the dir : creates a package where the project files will be stored. All the modules you download will be stored in the package.

  17. npm init -y
  18. Install the redis client for node:

  19. npm install redis
  20. Create a new javascript file in the same directory called app.js and enter the following code defined here

  21. touch basicRedisNode.js
  22. This creates a simple HTTP server that listens for requests on port 8000 and responds with "My First node server!" and additional header info.

  23. Start the server by running the following command in your terminal:

  24. node basiRedisNode
  25. This should output "Server running at http://127.0.0.1:8000/" to the console.

  26. To stop the server, press ctrl+c in the terminal.

  27. ^c
  28. If you have installed nodemon you can alternatively start the server with the following command :

  29. nodemon basicRedisNode.js
  30. This will start nodemon and automatically restart the server whenever you make changes to your code so you do not have to stop/restart the server manually following changes you make.

  31. To check if there are any servers running on a specific port and kill them if necessary, use the following commands, replacing 8000 with the port number you want to check, and {PID} with the process ID of the server you want to kill:

  32. lsof -i :8000
    kill -9 {PID}

basicRedisNode.js

               

// 1. Include dependencies and assign to variables const http = require("http"); const redis = require("redis"); // 2. Define constants to hold the configuration of where server will be bound const host = "localhost"; const port = 8000; // 3. Create the redis client const client = redis.createClient(); // 4. Define an async function where the client listens for events // When a connect event is received and the connection is established // We are able to then perform actions (async () => { await client.connect(); await client.set('myKey', 'myValue!'); const keyValue = await client.get('myKey'); console.log(keyValue); })();