How to Create a NodeJS API Without Using a Framework

Node.js is an open-source JavaScript runtime environment based on Chrome’s v8 engine that allows you to run JavaScript code outside of a browser.

Its event model, ecosystem, and speed have made Node.js one of the most sought-after and widely used runtimes for server-side applications.

Most Node.js API servers use Express or some other framework. But you can also create a simple Node.js API in just a few steps without a framework.


Step 1: Set up your development environment

Create a project directory and CD into it by running:

mkdir nodejs-api
cd nodejs-api

Next initialize nm in your project by running:

npm init -y

This CRUD API will involve using MongoDB, a NoSQL database, and their popular ODM, Mongoose.

Run the following command to install mongoose:

npm install mongoose

Next, create one server.js File in the root of your project and add the following code block to create a server:

const http = require("http");
const server = http.createServer((req, res) => {});

server.listen(3000, () => {
console.log(`Server is running`);
});

This block of code imports the HTTP module, a core module of Node.js. The http module allows Node.js to transfer data over HTTP. This module contains the methods required to create a server.

Next it calls the http module createServer Method that creates and returns an instance of a server. That createServer method takes a callback function with a Request and Response object as parameters.

Next, the code calls the Listen method on the returned server instance. This allows the server to start listening for traffic on the specified port. That Listen method triggers a callback – the second argument – if it succeeds.

Finally, create two directories named stretch and models in the root of your project. That stretch The folder contains the routing logic for your API, while model contains everything related to the database.

Step 2: Connect your application to a database

in the server.jsimport mongoose:

const mongoose = require("mongoose");

call the associate method on mongoose and pass your MongoDB URI as an argument:

mongoose.connect("MongoDB_URI")

Step 3: Create an API model

Build a CRUD API for a simple blog application. In your models folder, create one blogModel.js file and add the following code to your file:

const mongoose = require("mongoose");
const blogSchema = mongoose.Schema({
title: {
type: String,
required: [true, "Blog must have a title"],
},
body: {
type: String,
required: [true, "Blog must have a body"],
},
});
module.exports = mongoose.model("Blog", blogSchema);

The code block above creates a Mongo model with two properties and maps them to a MongoDB database.

Both properties in this model have a line type along necessary set to Is correct. The accompanying error messages are displayed when a request body does not contain any of the properties.

The last line creates and exports a Mungo model by using the model method on mongoose. Pass the model name (to blog) as the first argument and a scheme (blogSchema) as the second argument.

Step 4: Implement routing in your application

Without the help of frameworks like Express, you have to manually create the logic to handle each request to your API.

First create one blogRoutes.js file in your stretch folder and then import the blog mockup:

const Blog = require("../models/blogModel");

Next, create an asynchronous routers function, happen necessary and res as a parameter and export the function:

const router = async function (req, res) {};
module.exports = router;

This function contains all your routing logic.

Next, you implement route-by-route routing logic.

GET routes

Add the following block of code to yours routers Function to implement the RECEIVE Route handler for requests /api/blogs:


if (req.url === "/api/blogs" && req.method === "GET") {
const blogs = await Blog.find();

// set the status code and content-type
res.writeHead(200, { "Content-Type": "application/json" });


res.end(JSON.stringify(blogs));
}

The code block above checks the URL and method Properties of the request object. It then fetches all the blogs from the database via the Find Mungo model method (to blog).

Next it calls them writing head method on res, the response object. This method sends a response header with three arguments: a status code, an optional status message, and headers. That 200 The status code represents a successful response and the content type for this API call is set to application/json.

Finally, close the request to make sure the server isn’t hanging by calling the End method on res. The call to JSON.stringify converts the blogs object to a JSON string and pass that to the End method returns it as the response body.

Add the following block of code to yours routers Function to implement the RECEIVE Route handler for a single resource:


if (req.url.match(/\\/api\\/blogs\\/([0-9]+)/) && req.method === "GET") {
try {
const id = req.url.split("/")[3];


const blog = await Blog.findById(id);

if (blog) {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(blog));
} else {
throw new Error("Blog does not exist");
}
} catch (error) {
res.writeHead(404, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: error }));
}
}

This code uses the fit method that takes a regex expression as an argument to check if the URL conforms to the format: /api/blogs/.

Next, extract the I would property from the URL String by calling its Splits Method. This method takes a pattern as an argument (/), splits the string based on the pattern and returns an array. The third element of this array is the I would.

Finally, retrieve the document with the match I would from your database. If it’s there, send a response code of 200, close the request, and submit the fetched blog. If it doesn’t exist, throw an error and send it as a response in the catch block.

POST route

Add the following block of code to your router function to implement it POST Route handler:


if (req.url === "/api/blogs" && req.method === "POST") {
try {
let body = "";


req.on("data", (chunk) => {
body += chunk.toString();
});

// Listen for end event
req.on("end", async () => {
let blog = new Blog(JSON.parse(body));


await blog.save();
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(blog));
});
} catch (error) {
console.log(error);
}
}

The request object implements the Node.js ReadableStream interface. This stream broadcasts a Data and a End Event that grants you access to data from the request body.

This code waits for the data event and handles it by converting it to a string and concatenating it with the body Variable. In which End Event handler, it creates a to blog Instance containing the parsed text string. It then saves the new blog, sends the status code and content header, and closes the request.

PUT route

Add the following block of code to your router function to implement it PLACE Route handler:


if (req.url.match(/\\/api\\/blogs\\/([0-9]+)/) && req.method === "PUT") {
try {
const id = req.url.split("/")[3];
let body = "";

req.on("data", (chunk) => {
body += chunk.toString();
});
req.on("end", async () => {
// Find and update document
let updatedBlog = await Blog.findByIdAndUpdate(id, JSON.parse(body), {
new: true,
});

res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(updatedBlog));
});
} catch (error) {
console.log(error);
}
}

The PUT request handler is almost identical to that POST request handler, except that it extracts the I would property from the URL to update the corresponding blog.

DELETE route

Add the following block of code to your router function to implement yours CLEAR Route handler:

// DELETE: /api/blogs/:id
if (req.url.match(/\\/api\\/blogs\\/([0-9]+)/) && req.method === "DELETE") {
try {
const id = req.url.split("/")[3];

// Delete blog from DB
await Blog.findByIdAndDelete(id);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "Blog deleted successfully" }));
} catch (error) {
res.writeHead(404, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: error }));
}
}

This block of code extracts the I would of the URLdeletes the document with the matching one I wouldsends the status code and header and closes the request.

Finally import routers in your server.js File and call your routers function, passage necessary and res as arguments:

const router = require("./routes/blogRoutes");

const server = http.createServer((req, res) => {
router(req, res);
});

This allows your server to intercept requests and process them accordingly.

The completed project can be found in this GitHub repository.

Using a Node.js framework

While it’s possible to create a web API by hand, it can be a difficult task. You need to make sure you have covered many edge cases and your code better be bug free.

Over the years, developers have created frameworks like ExpressJS, NestJS, Fastify, etc. to make it much easier.

Leave a Reply

Your email address will not be published. Required fields are marked *