Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Building the CREATE Post Endpoint | Building REST APIs with Node.js and Express.js
Backend Development with Node.js and Express.js
course content

Course Content

Backend Development with Node.js and Express.js

Backend Development with Node.js and Express.js

1. Introduction to Node.js and Backend Development
2. Building Console Applications with Node.js
3. Developing Web Applications with Express.js
4. Building REST APIs with Node.js and Express.js

book
Building the CREATE Post Endpoint

We will examine creating a new post using the "CREATE POST" route within the postsRoutes.js file. This route is responsible for handling the creation of a post and saving it to the data source (database/posts.json).

Route Definition

The code below defines the "CREATE POST" route using router.post():

router.post("/", validatePostData, async (req, res, next) => { ... }
  • This route is configured to handle HTTP POST requests to the root path /;
  • It utilizes the validatePostData middleware, which ensures that the data sent in the request body is valid before proceeding.

Data Validation Middleware

Before delving into the route's logic, we must create a data validation middleware. This middleware ensures that the data sent in the request body is valid before attempting to create a new post.

// Middleware to validate post data
function validatePostData(req, res, next) {
  const { username, postTitle, postContent } = req.body;

  if (!username || !postTitle || !postContent) {
    return res.status(400).json({ error: "Missing required fields" });
  }

  // If data is valid, proceed to the next route handler
  next();
}
  • The validatePostData function extracts the username, postTitle, and postContent from the request body;
  • It checks whether these fields are present. If any of them are missing (!username, !postTitle, or !postContent), it responds with a 400 (Bad Request) status code and an error message indicating missing required fields;
  • If the data is valid, the middleware calls next(), allowing the request to continue to the route handler (the "CREATE POST" route in this case).

With the data validation middleware in place, let's continue with the "CREATE POST" route logic.

New Post Data

To create a new post, we generate a unique ID using Date.now().toString(). Additionally, we extract the username, postTitle, and postContent from the request body.

const newPost = {
  id: Date.now().toString(),
  username: req.body.username,
  postTitle: req.body.postTitle,
  postContent: req.body.postContent,
};

Add the New Post to the Database

The following steps detail how the new post is added to the database:

const data = await readData();
data.push(newPost);
await fs.writeFile("./database/posts.json", JSON.stringify(data));
  • The existing data is read from the JSON file using the asynchronous readData function, as previously explained;
  • The new post is added to the data array;
  • The updated data array is then written back to the JSON file to save the newly created post.

Sending a Response

Upon successful creation of the new post, a success response is sent to the client. The response includes a status code of 201 (Created) and the details of the newly created post in JSON format.

res.status(201).json(newPost);

Error Handling

We wrap the route code in a try-catch block to handle potential errors during data retrieval or request processing. Any errors that occur are logged to the console for debugging purposes:

try {
  // ... (code for retrieving and processing data)
} catch (error) {
  console.error(error.message);
}

Complete code of the postsRoutes.js file at this step

const express = require("express");
const fs = require("fs/promises");
const validatePostData = require("../middlewares/validateData");

const router = express.Router();

// Function to read data from the JSON file
async function readData() {
  try {
    // Read the contents of the `posts.json` file
    const data = await fs.readFile("./database/posts.json");
    // Parse the JSON data into a JavaScript object
    return JSON.parse(data);
  } catch (error) {
    // If an error occurs during reading or parsing, throw the error
    throw error;
  }
}

// GET ALL POSTS
router.get("/", async (req, res, next) => {
  try {
    // Call the `readData` function to retrieve the list of posts
    const data = await readData();
    // Send the retrieved data as the response
    res.status(200).send(data);
  } catch (error) {
    // If an error occurs during data retrieval or sending the response
    console.error(error.message); // Log the error to the console for debugging
  }
});

// GET POST BY ID
router.get("/post/:id", async (req, res, next) => {
  try {
    // Extract the post ID from the request parameters
    const postId = req.params.id;
    // Read data from the JSON file
    const data = await readData();

    // Find the post with the matching ID
    const post = data.find((post) => post.id === postId);

    // If the post is not found, send a 404 response
    if (!post) {
      res.status(404).json({ error: "Post not found" });
    } else {
      // If the post is found, send it as the response
      res.status(200).send(post);
    }
  } catch (error) {
    // Handle errors by logging them and sending an error response
    console.error(error.message);
  }
});

// CREATE POST
router.post("/", validatePostData, async (req, res, next) => {
  try {
    // Generate a unique ID for the new post
    const newPost = {
      id: Date.now().toString(),
      username: req.body.username,
      postTitle: req.body.postTitle,
      postContent: req.body.postContent,
    };

    // Read the existing data
    const data = await readData();

    // Add the new post to the data
    data.push(newPost);

    // Write the updated data back to the JSON file
    await fs.writeFile("./database/posts.json", JSON.stringify(data));

    // Send a success response with the new post
    res.status(201).json(newPost);
  } catch (error) {
    // Handle errors by logging them to the console
    console.error(error.message);
  }
});

Complete code of the validateData.js file

// Middleware to validate post data
function validatePostData(req, res, next) {
  const { username, postTitle, postContent } = req.body;

  if (!username || !postTitle || !postContent) {
    return res.status(400).json({ error: "Missing required fields" });
  }

  // If data is valid, proceed to the next route handler
  next();
}

module.exports = validatePostData;

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 4. ChapterΒ 7

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

course content

Course Content

Backend Development with Node.js and Express.js

Backend Development with Node.js and Express.js

1. Introduction to Node.js and Backend Development
2. Building Console Applications with Node.js
3. Developing Web Applications with Express.js
4. Building REST APIs with Node.js and Express.js

book
Building the CREATE Post Endpoint

We will examine creating a new post using the "CREATE POST" route within the postsRoutes.js file. This route is responsible for handling the creation of a post and saving it to the data source (database/posts.json).

Route Definition

The code below defines the "CREATE POST" route using router.post():

router.post("/", validatePostData, async (req, res, next) => { ... }
  • This route is configured to handle HTTP POST requests to the root path /;
  • It utilizes the validatePostData middleware, which ensures that the data sent in the request body is valid before proceeding.

Data Validation Middleware

Before delving into the route's logic, we must create a data validation middleware. This middleware ensures that the data sent in the request body is valid before attempting to create a new post.

// Middleware to validate post data
function validatePostData(req, res, next) {
  const { username, postTitle, postContent } = req.body;

  if (!username || !postTitle || !postContent) {
    return res.status(400).json({ error: "Missing required fields" });
  }

  // If data is valid, proceed to the next route handler
  next();
}
  • The validatePostData function extracts the username, postTitle, and postContent from the request body;
  • It checks whether these fields are present. If any of them are missing (!username, !postTitle, or !postContent), it responds with a 400 (Bad Request) status code and an error message indicating missing required fields;
  • If the data is valid, the middleware calls next(), allowing the request to continue to the route handler (the "CREATE POST" route in this case).

With the data validation middleware in place, let's continue with the "CREATE POST" route logic.

New Post Data

To create a new post, we generate a unique ID using Date.now().toString(). Additionally, we extract the username, postTitle, and postContent from the request body.

const newPost = {
  id: Date.now().toString(),
  username: req.body.username,
  postTitle: req.body.postTitle,
  postContent: req.body.postContent,
};

Add the New Post to the Database

The following steps detail how the new post is added to the database:

const data = await readData();
data.push(newPost);
await fs.writeFile("./database/posts.json", JSON.stringify(data));
  • The existing data is read from the JSON file using the asynchronous readData function, as previously explained;
  • The new post is added to the data array;
  • The updated data array is then written back to the JSON file to save the newly created post.

Sending a Response

Upon successful creation of the new post, a success response is sent to the client. The response includes a status code of 201 (Created) and the details of the newly created post in JSON format.

res.status(201).json(newPost);

Error Handling

We wrap the route code in a try-catch block to handle potential errors during data retrieval or request processing. Any errors that occur are logged to the console for debugging purposes:

try {
  // ... (code for retrieving and processing data)
} catch (error) {
  console.error(error.message);
}

Complete code of the postsRoutes.js file at this step

const express = require("express");
const fs = require("fs/promises");
const validatePostData = require("../middlewares/validateData");

const router = express.Router();

// Function to read data from the JSON file
async function readData() {
  try {
    // Read the contents of the `posts.json` file
    const data = await fs.readFile("./database/posts.json");
    // Parse the JSON data into a JavaScript object
    return JSON.parse(data);
  } catch (error) {
    // If an error occurs during reading or parsing, throw the error
    throw error;
  }
}

// GET ALL POSTS
router.get("/", async (req, res, next) => {
  try {
    // Call the `readData` function to retrieve the list of posts
    const data = await readData();
    // Send the retrieved data as the response
    res.status(200).send(data);
  } catch (error) {
    // If an error occurs during data retrieval or sending the response
    console.error(error.message); // Log the error to the console for debugging
  }
});

// GET POST BY ID
router.get("/post/:id", async (req, res, next) => {
  try {
    // Extract the post ID from the request parameters
    const postId = req.params.id;
    // Read data from the JSON file
    const data = await readData();

    // Find the post with the matching ID
    const post = data.find((post) => post.id === postId);

    // If the post is not found, send a 404 response
    if (!post) {
      res.status(404).json({ error: "Post not found" });
    } else {
      // If the post is found, send it as the response
      res.status(200).send(post);
    }
  } catch (error) {
    // Handle errors by logging them and sending an error response
    console.error(error.message);
  }
});

// CREATE POST
router.post("/", validatePostData, async (req, res, next) => {
  try {
    // Generate a unique ID for the new post
    const newPost = {
      id: Date.now().toString(),
      username: req.body.username,
      postTitle: req.body.postTitle,
      postContent: req.body.postContent,
    };

    // Read the existing data
    const data = await readData();

    // Add the new post to the data
    data.push(newPost);

    // Write the updated data back to the JSON file
    await fs.writeFile("./database/posts.json", JSON.stringify(data));

    // Send a success response with the new post
    res.status(201).json(newPost);
  } catch (error) {
    // Handle errors by logging them to the console
    console.error(error.message);
  }
});

Complete code of the validateData.js file

// Middleware to validate post data
function validatePostData(req, res, next) {
  const { username, postTitle, postContent } = req.body;

  if (!username || !postTitle || !postContent) {
    return res.status(400).json({ error: "Missing required fields" });
  }

  // If data is valid, proceed to the next route handler
  next();
}

module.exports = validatePostData;

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 4. ChapterΒ 7
some-alt