DEV Community

Abhinav Anand
Abhinav Anand

Posted on

Building My First Full-Stack App: Part 2 - Crafting the Node.js Backend for Face Detection

Setting Up the Node.js and Express.js Server

Initializing the Project

I started by creating a dedicated folder for the server and ran npm init to set up the basic Node.js package.json file. After that, I created the main server file, server.js.

Express.js Fundamentals in Action

To get the server running, I installed Express.js by running npm install express.

My basic server setup in server.js looked like this:

import express from 'express';
const app = express();

// Root route to test if the server is working
app.get('/', (req, res) => {
res.json('working');
});`

`app.listen(3000, () => {
console.log('Server is running on port 3000');
});

I tested this root route with Postman.com to confirm the server was up and running.

A Crucial Middleware Lesson: Parsing Request Bodies

During initial testing, I quickly encountered an error. The server wasn't able to read the incoming request bodies from the frontend. After some investigation, I realized I'd forgotten to add the necessary middleware to parse the response. To fix this, I simply added app.use(express.json()). With this in place, my server could now correctly interpret JSON data sent from the frontend, and everything started working as expected.


Designing API Endpoints for Face Detection

Planning the API Structure

Before diving into implementation, I like to outline the overall structure of my API endpoints. This planning phase simplifies development, even for a smaller number of routes. My planned structure looked something like this:

/*
/signin --> POST = will respond => success/failed
/register --> POST = will respond => user
/profile/:id --> GET = will respond => user
/image --> PUT = will respond => updated user's data
*/

Now, let's create each of these API endpoints step by step.

The /signin Endpoint

To test this endpoint, I started with a simple, temporary fake database containing two users. This allowed me to simulate authentication without setting up a full database yet.

Here's the initial sign-in route I created:

app.post('/signin', (req, res) => {
const { email, password } = req.body; // Destructuring for cleaner code
// For simplicity during testing, hardcoded a single user for authentication.
if (database.user[0].email === email && database.user[0].password === password) {
res.json('success');
} else {
res.status(400).json('Invalid Credentials');
}
});

The /register Endpoint

For the registration route, I simulated adding a new user to our temporary database using the array's push method:

app.post('/register', (req, res) => {
const { email, name, password } = req.body;
database.users.push({
id: '125',
name: name,
email: email,
password: password,
entries: 0,
joined: new Date()
});
res.json(database.users[database.users.length - 1]);
});

The /profile/:id Endpoint

While not immediately used by the frontend in this version, I included this route for future expandability, allowing users to view their profiles later.

JavaScript

app.get('/profile/:id', (req, res) => {
const { id } = req.params;
let found = false;
database.users.forEach(user => {
if (user.id === id) {
found = true;
return res.json(user);
}
});
if (!found) {
res.status(404).json('User Not Found');
}
});

The /image Endpoint

This endpoint is designed to receive a user ID and increment their entries count, similar to the profile route.

JavaScript

app.put('/image', (req, res) => {
const { id } = req.body;
let found = false;
database.users.forEach(user => {
if (user.id === id) {
found = true;
user.entries++;
return res.json(user.entries);
}
});
if (!found) {
res.status(404).json('User Not Found');
}
});

After implementing each endpoint, I thoroughly tested it using Postman before moving to the next, ensuring functionality.


Crucial for Full-Stack: Understanding and Implementing CORS

All necessary endpoints were created and tested. It was time to connect them to the frontend. However, after connecting the sign-in endpoint and testing it with my frontend, I encountered the infamous CORS (Cross-Origin Resource Sharing) issue.

The browser console showed that the request was blocked due to "no-cors." After doing some research, I understood that CORS ensures security by allowing controlled sharing of resources across different origins (domains) in a web browser. The backend is the proper place to handle this issue because it ensures that security rules are consistently applied and cannot be bypassed by malicious clients.

To solve this, I added the cors middleware to the backend. I installed it using npm install cors, imported it (import cors from 'cors'), and then added it as middleware (app.use(cors())). With this, the sign-in endpoint now works perfectly with the frontend.


Conclusion: The Backend's Power and What's Next

In this part, we successfully built and connected a foundational backend server to our frontend. While currently using a mock database for initial testing, this setup was crucial for establishing the core application flow.

I learned a lot in this phase, including:

  • The value of outlining basic server endpoints before connecting to a final database.
  • How to efficiently test API endpoints using Postman.com.
  • The importance of express.json() middleware for parsing request bodies.
  • The practical steps to connect backend endpoints to a frontend.
  • How to identify and effectively handle CORS issues in a full-stack application.
  • The fundamental concepts of backend server development.

A Note on Clarifai API Integration (Next Steps)

You might have noticed that I haven't moved the Clarifai API integration to the backend in this specific part. My development approach was to first ensure all core components (frontend, backend server, and eventually database) were functional and communicating correctly. In a later refinement stage, or in a subsequent blog post, I'll integrate the Clarifai API directly into this backend for enhanced security and a more robust application architecture.

What's Coming in Part 3

Now that our frontend and backend are communicating, the next logical step is to introduce persistence! In Part 3, we'll dive into the database part. We'll talk about how I created the database and connected it to the backend server using Knex.js.

Please don't forget to share your thoughts and leave comments about this blog. I'm always open to advice, so if you find something that needs to be changed or can be improved, just tell me!

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.