
API development is an essential part of almost every software application process today. With API development, businesses can easily expand their software architectures, communicate easily with client applications, and create standards. In addition, businesses can provide services to external systems and earn money with the APIs they develop. Today, REST APIs are the popular API protocols for API development.
REST APIs are API protocols that can be developed in almost any programming language. It is even possible in many programming languages to run a REST API in just a few steps. This article will introduce the very useful REST API more closely. Then, we will create a REST API project by going step by step with the Node.js programming language.
Table of Contents
What is the REST API?
REST API (Representational State Transfer API) is an architectural style or approach for web applications. This approach provides a standard set for data communication between client and server. REST APIs run on the HTTP protocol and provide a powerful interface to represent and manage resources using HTTP methods (GET, POST, PUT, DELETE, etc.).
Learn how the REST API works.
REST APIs promote independence and scalability between client and server. While receiving data from the server, the client can create new resources, update existing resources, or delete them by sending a request to the server. Also, REST APIs support many data transfer formats for data transfer. JSON, XML, and CSV are just a few of them.
What are the Principles of the REST API?
The REST API protocol is built on a set of principles and restrictions.
One of the basic principles of the REST API is that the server is stateless. It does not keep a client-related context or session on that server side. Each request the client makes carries the necessary information for the server to respond. In other words, all kinds of states are kept on the client side, and if needed, it is reported to the server in the request. This is also important in terms of scalability because it makes it unnecessary for the server to store any state between requests and makes resource management easier.
The REST API adopts a client-server model. When the client receives data from the server, it sends a service request to the server and receives a response from the server. This structure ensures that the client and server are independent and interchangeable. The independence of the client and server provides advantages in terms of modularity, scalability, and maintainability of applications.
RESTful APIs have a unified interface. This interface represents and manages resources using HTTP methods (GET, POST, PUT, DELETE). Also, how resources are defined, media types and other standards are part of this unified interface.
Finally, REST APIs can cache the server’s responses or give the client the ability to cache. This improves performance and reduces network traffic. The server’s caching capability provides a faster response to recurring requests made by the client.
How to Develop Restful API in Node.js
In this part, we will develop a RESTful API application with Node.js programming language. This application will perform CRUD (Create, Read, Update, Delete) operations on the ‘Product’ model. We will create and use a free database from MongoDB Cloud as a database.
Create Database on MongoDB Cloud
Before starting application development, we must create a database instance in MongoDB Cloud. For this, let’s register and log in to the MongoDB Cloud website. After the login process, let’s go to the ‘Project’ page and press the ‘New Project’ button here. Let’s enter the name of our database project on the screen that opens.
Then, let’s press the ‘Next >> Create Project’ buttons, respectively.
Now we will create a database for our project. For this, let’s press the ‘Build a Database’ button on the page of our project. At this stage, let’s choose the ‘Free’ item and press the ‘Create’ button to progress for free.
Then, let’s create our database by making the user information and network settings that will access the database.
Create Node.js Application
After completing our database operations, let’s create a Node.js project to develop our application. For this, let’s open a terminal in the file path we want to develop the application and proceed with the default options.
1 |
npm init |
Then let’s open a file named ‘index.js’ in this file path.
Install Libraries
Now we will download the libraries that we will use in our application. These libraries are:
- Express: A popular web framework for developing Node.js-based web applications. Express provides basic HTTP functionality, such as web server and route routing, and offers developers a flexible structure for building APIs and web applications.
- Joi: Joi is a validation library used to validate and process input data in a Node.js environment. Joi provides schema-based validation, thus allowing you to check if the data conform to a certain format or convention.
- MongoDB: It is an official MongoDB driver. It is used to connect the Node.js application to the MongoDB database and perform operations on this database.
To download and install these libraries in our application, let’s open a terminal in the file path where the application is installed and run the following command:
1 |
npm i express joi mongodb |
API Development Project Structure
After downloading the necessary libraries to our application, we can now talk about the project structure.
The project structure will consist of one folder and four folders below it. The name of the main folder containing the code of the project will be ‘src’. The subfolders are ‘controller’, ‘model’, ‘route’, and ‘service’, respectively.
Discover the best practices for REST API design!
- Controller: Controller folder receives HTTP requests and contains functions that execute the relevant business logic. The controllers in this folder direct the incoming requests to the model and perform the necessary data manipulation.
- Model: Model folder defines the data models associated with the MongoDB database. Each model represents a collection or table in the database and ensures that data is stored with the correct format and restrictions.
- Route: Route folder contains the route definitions that forward HTTP requests to the corresponding controllers. Here, Express.js route definitions are made, and requests made by the client are forwarded to the relevant controllers.
- Service: Service folder contains the service layer where the business logic is performed. Here, the operations used in the controllers and database operations are performed. Services isolate controllers and avoid code duplication.
API Development Code
Now we can start writing the code. For this, let’s start with the ‘model’ folder. In this file, we will define the Product model and the required fields. Let’s open a file named ‘product.js’ inside this folder and put the following code in it:
product.js
1 2 3 4 5 6 7 8 |
class Product { constructor( name, price) { this.name = name; this.price = price; } } module.exports = Product; |
Then, let’s open a file named ‘productRoute.js’ in the ‘route’ folder where we will perform the routing operations. We will paste the following codes into this file.
productRoute.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
const express = require('express'); const Joi = require('joi'); class ProductsRoutes { constructor(productsController) { this.productsController = productsController; this.router = express.Router(); this.initializeRoutes(); } initializeRoutes() { this.router.get('/', this.productsController.getProducts.bind(this.productsController)); this.router.get('/:id', this.validateId(), this.productsController.getProductById.bind(this.productsController)); this.router.post('/', this.validateProduct(), this.productsController.addProduct.bind(this.productsController)); this.router.put('/:id', this.validateId(), this.validateProduct(), this.productsController.updateProduct.bind(this.productsController)); this.router.delete('/:id', this.validateId(), this.productsController.deleteProduct.bind(this.productsController)); } validateId() { return (req, res, next) => { const { error } = Joi.object({ id: Joi.string().length(24).hex() }).validate(req.params); if (error) { res.status(400).json({ error: 'Invalid ID' }); } else { next(); } }; } validateProduct() { return (req, res, next) => { const schema = Joi.object({ name: Joi.string().required(), price: Joi.number().min(0).required() }); const { error } = schema.validate(req.body); if (error) { res.status(400).json({ error: 'Invalid product data' }); } else { next(); } }; } } module.exports = ProductsRoutes; |
In this file, we created our routers and connected these routes with the relevant methods in the productController.js file that we will create in the next step. Also in this file, we have two validation methods named ‘validateId’ and ‘validateProduct’. These methods use the ‘Joi’ library to perform validation of the required input data.
Now we can create our Product Controller. For this, we will create a JavaScript file named ‘productController’ in the ‘controller’ folder. This file combines the requests directed from the ‘productRoute.js’ file with the related database operations and returns a response to the client.
productController.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
const { ObjectId } = require('mongodb'); const Product = require('../model/product'); class ProductsController { constructor(databaseService) { this.databaseService = databaseService; } async getProducts(req, res) { try { const products = await this.databaseService.getProducts(); res.json(products); } catch (error) { res.status(500).json({ error: 'Internal server error' }); } } async getProductById(req, res) { try { const id = req.params.id; if (!ObjectId.isValid(id)) { res.status(400).json({ error: 'Invalid ID' }); return; } const product = await this.databaseService.getProductById(new ObjectId(id)); if (!product) { res.status(404).json({ error: 'Product not found' }); } else { res.json(product); } } catch (error) { res.status(500).json({ error: 'Internal server error' }); } } async addProduct(req, res) { try { const { name, price } = req.body; const product = new Product(name, price); await this.databaseService.addProduct(product); res.json(); } catch (error) { res.status(500).json({ error: 'Internal server error' }); } } async updateProduct(req, res) { try { const id = req.params.id; if (!ObjectId.isValid(id)) { res.status(400).json({ error: 'Invalid ID' }); return; } const { name, price } = req.body; const product = new Product(name, price); const result = await this.databaseService.updateProduct(new ObjectId(id), product); if (result.matchedCount === 0) { res.status(404).json({ error: 'Product not found' }); } else { res.json(product); } } catch (error) { res.status(500).json({ error: 'Internal server error' }); } } async deleteProduct(req, res) { try { const id = req.params.id; if (!ObjectId.isValid(id)) { res.status(400).json({ error: 'Invalid ID' }); return; } const result = await this.databaseService.deleteProduct(new ObjectId(id)); if (result.deletedCount === 0) { res.status(404).json({ error: 'Product not found' }); } else { res.json({ message: 'Product deleted successfully' }); } } catch (error) { res.status(500).json({ error: 'Internal server error' }); } } } module.exports = ProductsController; |
Now we will create the file where we will perform the database operations. For this, let’s open a file named ‘database.js’ under the ‘service’ folder and put the following codes in this file.
database.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
const { MongoClient } = require('mongodb'); class DatabaseService { constructor(dbUrl) { this.dbUrl = dbUrl; this.client = new MongoClient(this.dbUrl); } async connect() { try { await this.client.connect(); console.log('Connected to MongoDB'); this.db = this.client.db(); } catch (error) { console.error('Error connecting to MongoDB:', error); } } async disconnect() { try { await this.client.close(); console.log('Disconnected from MongoDB'); } catch (error) { console.error('Error disconnecting from MongoDB:', error); } } async getProducts() { return await this.db.collection('products').find().toArray(); } async getProductById(id) { return await this.db.collection('products').findOne({ _id: id }); } async addProduct(product) { return await this.db.collection('products').insertOne(product); } async updateProduct(id, product) { return await this.db.collection('products').updateOne({ _id: id }, { $set: product }); } async deleteProduct(id) { console.log("id: ", id) return await this.db.collection('products').deleteOne({ _id: id }); } } module.exports = DatabaseService; |
Now, as the last step, we will put the relevant codes in the ‘index’ file of the application. For this, let’s open the ‘index.js’ file and put the following codes in this file.
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
const express = require('express'); const DatabaseService = require('./src/service/database'); const ProductsController = require('./src/controller/productController'); const ProductsRoutes = require('./src/route/productRoute'); const app = express(); const port = 3000; // Creating database service const databaseService = new DatabaseService('mongodb+srv://app-user:<YOUR-DB-PASSWORD>@cluster0.fvzpvpd.mongodb.net/?retryWrites=true&w=majority'); // Connecting database databaseService.connect(); const productsController = new ProductsController(databaseService); const productsRoutes = new ProductsRoutes(productsController); app.use(express.json()); app.use('/api/v1/products', productsRoutes.router); app.listen(port, () => { console.log(`Server listening on port ${port}`); }); |
With this file, we determined the general structure of the application, created the necessary objects, and added the database connection string. We obtained the database connection string by clicking the ‘Connect’ button in the cluster we created in MongoDB Cloud. Before running the application, let’s write our own password in the ‘<YOUR-DB-PASSWORD>’ field.
Try today’s best free SERP API!
Test
We have successfully created our application. Now we can start testing. For this, first, let’s open a terminal in the file path of the application and run the application with the following command.
1 |
node index.js |
Then, on the console screen of the application, we will see that the application has started successfully and the database connection has been made successfully.
1 2 |
Server listening on port 3000 Connected to MongoDB |
et’s open the Postman application and import the following cURL.
1 2 3 4 5 6 |
curl --location --request POST 'http://localhost:3000/api/v1/products/' \ --header 'Content-Type: application/json' \ --data-raw '{ "name": "Product-1", "price": 9.99 }' |
Then let’s send HTTP POST requests and create a resource in their collection.
Now, let’s import the following cURL request to Postman to fetch the source we created with Node.js from the database.
1 2 |
curl --location --request GET 'http://localhost:3000/api/v1/products/' \ --data-raw '' |
When we send an HTTP GET request to this endpoint with Postman, the response we will get will be as follows.
API Development: Conclusion
One of the most preferred API protocols for API developers today is the REST API. REST API can be easily developed in just a few steps with Node.js, Golang, Python, and many more programming languages. In this way, developers who choose and use the REST API protocol can take advantage of all its advantages and flexibility in just a few steps.
Sell your REST API product with our remarkable REST API products, and make your service reach wide audiences easily.
API Development: FAQs
Q: What are the Key Principles of REST Architecture?
A: The key principles of the REST architecture are as follows:
- Statelessness
- Client-Server Separation
- Uniform Interface
- Cacheability
- Layered Architecture
Q: Why is Node.js Preferred for Developing REST APIs?
A: Node.js is a programming language frequently preferred by developers to develop RESTful APIs. Here are some reasons why Node.js is preferred for developing REST APIs:
- High performance
- JavaScript Based
- Large Ecosystem
- Good Scalability
Q: What Should I Pay Attention to for API Development?
A: There are many points to consider when developing an API. The first of these is to comply with API development design principles. Next, you must ensure the security of the API you will develop. Input validation and error management are also very important for API development. Finally, you should pay attention to performance and scalability issues.
Q: What are the Most Popular API Protocols?
A: Today, the most preferred API protocols in software applications are:
- REST
- GraphQL
- OData
- SOAP
- gRPC
Sign Up for free at APILayer to get your best RESTful API for creating web applications.