Hey tech writers, in this year-end blog, we’re immersing ourselves in the intricacies of designing, creating, and documenting REST APIs using Node.js, Express, and Swagger. This hands-on experience goes beyond theoretical jargon, offering a festive extravaganza of learning just in time for the holidays—a special gift from me to you!
Why settle for just reading when you can actively participate? Together, let’s delve into the domain of API coding, exploring how to design REST APIs while adhering to REST principles. We’ll navigate the application design process, manage resources effectively, and bring a touch of holiday cheer to our coding endeavors. Equipped with your virtual Santa hat and coding gloves, follow along by copying and pasting the provided code snippets, turning this blog into a catalyst for your own festive tech magic.
The best developer is someone who knows how to find the code, not the one who has memorized everything. And the best tech writer is someone who knows how to use and document what the developer has found, rather than recite dry facts.
Let the coding celebration begin! 🎅🎄
Prerequisites - The Enchanted Preparations
As we begin our magical journey, picture yourself adorned in wizarding robes, standing before the majestic gates of Hogwarts – our code school. But before we can cast spells, we must complete our magical prerequisites.
Regardless of your operating system, open your terminal and:
Procedures - The Code Incantations
- Create a directory for your project. Let’s name it
rest_api
. In your terminal, runmkdir rest_api
. - Navigate to the directory you just created using
cd rest_api
. -
Initialize your project by running
npm init
. For simplicity, press Enter until you’re back on the path. This step creates anode_modules
directory and generatespackage-lock.json
andpackage.json
files. In the terminal, you can verify this by runningls
, or alternatively, open your project in Visual Studio Code. If you’re not comfortable with the terminal, don’t worry—feel free to open your project in Visual Studio Code. I’ll continue with the Terminal for now. - Create an empty JavaScript file named
index.js
. If you are working on the Terminal run,echo index.js
. - Install Express by running
npm install express
. -
Open the
index.js
file. If you are on terminal entervim index.js
and if you are on Visual Studio code, simply open it and paste the following code:const express = require('express'); const app = express(); const port = 3000; app.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); });
Note: If you get errors when runningvim index.js
, it meansvim
is not installed on your system. Installvim
and run the command again.Note: Usingapp.use(express.json())
, we tell Express to parse incoming JSON requests and make the data available inreq.body
.Expand for code explanation
Once upon a time in the coding kingdom, a developer wanted to create a special place on the internet. They decided to use Express.js, a helpful tool that makes building websites easier.
Getting the Toolbox (Importing Express.js): Our hero started by getting a toolbox called Express.js using `const express = require('express');`. This toolbox has all sorts of tools to help build websites. The developer named it 'express'.
Setting Up the Workspace (Creating Express App Instance): With the toolbox ready, our hero created a workspace, a space to build their website. The line `const app = express();` creates an instance of the Express application. They called it 'app'. This is where all the website-building would happen. In other words, this `app` variable will be used to configure the server and define routes.
Choosing a Door (Setting a Port Number): Every website needs a door for people to come in. Our hero chose the number 3000 as the door number. So, people could visit the website at http://localhost:3000. The code sets a port number for the server to listen on with `const port = 3000;`. The server will be accessible through http://localhost:3000/.
Opening for Business (Starting the Server): The hero opened the door and let the website start. They used a special command, `app.listen(port, () => {...});`, to make the website live. The hero also left a message saying, "Hey, the website is running at http://localhost:3000!". The arrow function `() => {...}` is a callback that logs a message to the console once the server is successfully started.
The Website Is Open (Server Running Message): Now, the website was open for everyone to visit. People could type http://localhost:3000 in their browsers and see what our hero built. The server will keep running until manually stopped or in case of an error. The console log inside the callback provides a message indicating that the server is running and on which URL. - (Optional) If you’re using Vim, save and close the file by typing
:wq
. - Launch your terminal and run
node index.js
. If everything works as expected, you’ll see a message confirming the server is running on http://localhost:3000. Copy this address and paste it into your web browser. - What is the result? Encounter a “Cannot GET /”? Excellent!
Creating an Enhanced POST Endpoint
-
Let’s elevate our code by creating an enhanced POST Endpoint.
const express = require('express'); const app = express(); const port = 3000; // Define the users array const users = []; // Middleware to parse JSON body app.use(express.json()); // GET endpoint to retrieve users app.get('/users', (req, res) => { // Logic to retrieve and send users res.json(users); }); // POST endpoint to add a new user app.post('/users', (req, res) => { const { name, email } = req.body; if (!name || !email) { return res.status(400).send('Name and email are required'); } // Logic to add the user to the array const newUser = { id: users.length + 1, name, email, }; users.push(newUser); res.status(201).json(newUser); }); // Start the server app.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); });
Expand for code explanation
Continuing the developer's journey in the coding kingdom, our hero extended their creation, weaving a more intricate tale of a dynamic and interactive place on the internet using Express.js. The developer not only built a place but also added functionality to manage a community within it.
Expanding the Kingdom with Interactive Features: After establishing the initial internet haven, our innovative developer decided to transform it into a lively community. To accomplish this, they introduced new features to the Express.js kingdom.
Gathering the Inhabitants (Defining the Users Array): Our hero recognized the need to track the inhabitants of the growing community. Introducing a new array called `users` using `const users = [];`, the hero started keeping records of the community members. This array would store details about each inhabitant in the kingdom.
Creating a Common Language (Middleware to Parse JSON Body): To facilitate communication within the community, our developer implemented a middleware using `app.use(express.json());`. This feature allowed the community members to speak a common language by parsing incoming messages in JSON format.
Opening the Community Records (GET Endpoint to Retrieve Users): Our hero wanted the community to be transparent, allowing others to explore its members. They created a pathway at `/users` with a special gate that responded to GET requests. When someone ventured to this path, the hero opened the community records (`users` array) to share the diverse profiles of its members.
Welcoming New Residents (POST Endpoint to Add a New User): The hero wanted to welcome new residents to the community. To achieve this, they crafted another pathway at `/users` for POST requests. If a visitor brought a name and an email, they were warmly welcomed as new members. The hero diligently recorded their information in the community records (`users` array) and offered a unique identifier (`id`) as a token of membership.
Reiterating the Grand Announcement (Start the Server): With every new enhancement, our hero proudly reiterated the grand announcement, declaring the continued expansion of the interactive community using `app.listen(port, () => {...});`. Once again, the message echoed through the digital realm, proclaiming, "The vibrant community is open for exploration at http://localhost:3000!"
Test the POST Endpoint
Now, let’s test our API using Postman.
-
Open Postman, navigate to Collections > REST API basics: CRUD, test, & variable > Post data.
-
Send a POST request to http://localhost:3000/users with a JSON body containing “name” and “email” fields.
{ "name": "John Doe", "email": "john.doe@example.com" }
-
Select Send. What do you see in the Response section? If you don’t see the expected response, close your server and restart it by running
node index.js
.
Documenting API
-
In your project terminal, run the following command to install the required packages.
npm install swagger-jsdoc swagger-ui-express
-
Let’s update our endpoint to add Swagger definition.
const express = require('express'); const app = express(); const port = 3000; const swaggerJSDoc = require('swagger-jsdoc'); const swaggerUi = require('swagger-ui-express'); // Swagger definition const swaggerOptions = { definition: { openapi: '3.0.0', info: { title: 'Your API', version: '1.0.0', }, }, apis: [__filename], // Point to the current file }; const swaggerSpec = swaggerJSDoc(swaggerOptions); app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec)); // Define the users array const users = []; // Middleware to parse JSON body app.use(express.json()); // GET endpoint to retrieve users /** * @swagger * /users: * get: * summary: Get a list of users * responses: * 200: * description: Successful response * content: * application/json: * example: [{"id": 1, "name": "John Doe"}, {"id": 2, "name": "Jane Smith"}] */ app.get('/users', (req, res) => { // Logic to retrieve and send users res.json(users); }); // POST endpoint to add a new user /** * @swagger * /users: * post: * summary: Add a new user * requestBody: * content: * application/json: * example: {"name": "John Doe", "email": "john.doe@example.com"} * responses: * 201: * description: User created successfully * content: * application/json: * example: {"id": 3, "name": "John Doe", "email": "john.doe@example.com"} * 400: * description: Bad Request * content: * text/plain: * example: "Name and email are required" */ app.post('/users', (req, res) => { const { name, email } = req.body; if (!name || !email) { return res.status(400).send('Name and email are required'); } // Logic to add the user to the array const newUser = { id: users.length + 1, name, email, }; users.push(newUser); res.status(201).json(newUser); }); // Start the server app.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); });
Expand for code explanation
Once upon a time in the coding kingdom, our resourceful developer continued their journey, building upon the foundation of the Express.js kingdom. But this time, they added a dash of magic with Swagger, a tool that effortlessly documents the kingdom's APIs.
Extending the Kingdom's Reach (Importing Express.js and Swagger): Expanding their toolkit, our hero summoned Express.js once again using `const express = require('express');`. Additionally, they introduced Swagger to the realm with `const swaggerJSDoc = require('swagger-jsdoc');` and `const swaggerUi = require('swagger-ui-express');`.
Designing New Blueprints (Swagger Definition): With the magic of Swagger, our hero designed new blueprints for the kingdom's APIs. This time, they added more details to the Swagger options, specifying the API title and version. The incantation looked like this: `const swaggerOptions = {...};`, and the enchanting Swagger specification emerged with `const swaggerSpec = swaggerJSDoc(swaggerOptions);`.
Creating a Seamless Gateway (Swagger UI Middleware): To provide a seamless experience for visitors, our hero crafted a new gateway at `/api-docs` using `app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));`. This gateway, powered by Swagger UI, allowed anyone to easily explore and understand the magical APIs of the kingdom.
Introducing New Inhabitants (Defining the Users Array): The hero continued to populate the kingdom, introducing a new array called `users` using `const users = [];`. This array would hold information about the growing number of inhabitants within the API kingdom.
Enabling Clear Communication (Middleware to Parse JSON Body): To ensure clear communication between the kingdom and the outside world, our hero reinforced the gateway using `app.use(express.json());`. This enhancement enabled messages in JSON format to seamlessly flow into and out of the API kingdom.
Opening Updated Census Records (GET Endpoint to Retrieve Users): The hero extended the pathways for exploration, maintaining the `/users` route with a special gate that responded to GET requests. When curious visitors ventured to this path, the hero graciously opened the updated census records (`users` array) to share the ever-expanding information.
Welcoming New Citizens (POST Endpoint to Add a New User): With the kingdom flourishing, our hero set up a welcoming pathway at `/users` for POST requests. If a visitor brought a name and an email, they were warmly welcomed as new citizens. The hero diligently recorded their details in the census records (`users` array) and bestowed upon them a special token (`id`) as a symbol of their newfound citizenship.
Repeating the Grand Announcement (Start the Server): With every enchantment in place, our hero repeated the grand announcement, proclaiming the continued expansion of the API kingdom using `app.listen(port, () => {...});`. Once again, the message echoed through the digital realm, declaring, "The API kingdom is open for exploration at http://localhost:3000!" -
When you run your server (
node index.js
), access the Swagger documentation at http://localhost:3000/api-docs. This page offers clear and interactive documentation of your API, including endpoints, parameters, request/response examples, and more.
You did it! You’ve become a coder, a documentarian, and a magician – all in one go. Your API is not just a set of endpoints; it’s a masterpiece, a testament to your newfound skills.
As you journey through the tech realm, remember this: APIs aren’t just about coding. They’re about telling a story, creating an experience. So, go forth, write beautiful APIs, document them with Swagger, and sprinkle a bit of humor along the way.
In the words of our digital sages: “May your code be bug-free, your documentation crystal clear, and your laughter contagious.” Until next time, happy coding, and may the tech gods be ever in your favor!