Skip to main content

Command Palette

Search for a command to run...

Creating Routes & Handling Requests with Express.js

Updated
10 min read

If you’ve ever tried building a web server using only built-in Node.js modules, you know it can get complicated quickly. Enter Express.js, the most popular web framework for Node.js. It’s designed to make building web applications and APIs much faster and easier.

What is Express.js?

Imagine you want to open a restaurant. You could build every piece of kitchen equipment from scratch — the oven, the refrigerator, the dishwasher. Or, you could buy reliable appliances that already exist and focus on cooking great food.

Express.js is like those appliances — for web servers. It is a framework (a toolbox of ready-made code) that sits on top of Node.js and makes it dramatically easier to handle web requests, define URL routes, and send responses back to users.

📌 Definition

Express.js is a minimal and flexible web framework for Node.js. It provides tools for creating web servers, defining URL routes, and sending responses back to clients (like browsers or mobile apps).

Express.js was created in 2010 and is still the most widely used framework for Node.js today because it’s minimal, flexible, and supported by a large community. When someone visits a website or uses an app, their browser sends an HTTP request to a server, and Express makes it easy for the server to understand that request and send back the correct response—whether it’s an HTML page, data, or a simple status message.

Why Express simplifies Node.js development

Node.js can build web servers on its own — but the code gets verbose and repetitive fast. Express wraps all that boilerplate so you write less and do more.

Let's compare the same task — creating a simple web server that says "Hello!" — using raw Node.js versus Express. This will show you exactly what Express saves you from writing.

Without Express (Raw Node)

const http = require('http');

const server = http.createServer(
  (req, res) => {
    if (req.url === '/'
     && req.method === 'GET') {
      res.writeHead(200, {
        'Content-Type': 'text/plain'
      });
      res.end('Hello!');
    } else {
      res.writeHead(404);
      res.end('Not Found');
    }
  }
);

server.listen(3000);

With Express

const express = require('express');
const app = express();


app.get('/', (req, res) => {
  res.send('Hello!');
});




app.listen(3000);

Both do the same thing. But Express is shorter, cleaner, and easier to read. And as your app grows with dozens of routes, the difference becomes even more dramatic. Express also handles 404 errors, JSON parsing, and much more — automatically.

💡 Key Benefits

Express gives you clean route definitions, built-in response helpers like res.json(), automatic error handling, and a huge ecosystem of plugins called "middleware."

Creating your first Express server

Let's build a working Express server from scratch. You'll need Node.js installed on your computer. If you haven't already, download it from nodejs.org.

  1. Create a new project folder
    Open your terminal and run these commands to create a project and install Express.
// Create a new folder for your project
mkdir my-express-app
cd my-express-app

// Set up the project (creates a package.json file)
npm init -y

// Install Express
npm install express
  1. Create your server file
    Create a file called server.js and add the following code.
// Step 1: Import Express
const express = require('express');

// Step 2: Create an Express "app" (your server)
const app = express();

// Step 3: Define a route (more on this soon!)
app.get('/', (req, res) => {
  res.send('Hello from Express!');
});

// Step 4: Start listening on port 3000
app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});
  1. Run your server
    In the terminal, run node server.js then open your browser and go to http://localhost:3000. You should see "Hello from Express! ".

📖 Understanding the code

require('express') loads the library. express() creates your app. app.listen(3000) tells your server to watch for requests on port 3000 — like saying "stand at door number 3000 and wait for visitors."

Handling GET requests

A GET request is what happens when you type a URL into your browser. You're asking the server: "Give me this page or this data." It's the most common type of request.

In Express, you define a GET route using app.get(). It takes two things: the URL path (like /about) and a handler function that decides what to send back.

const express = require('express');
const app = express();

// Homepage — responds with a simple welcome message
app.get('/', (req, res) => {
  res.send('Welcome to the homepage!');
});

// /about — responds with a different message
app.get('/about', (req, res) => {
  res.send('This is the about page.');
});

// /users — responds with a list of users (as JSON)
app.get('/users', (req, res) => {
  const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
  ];
  res.json(users); // Send back JSON data
});

app.listen(3000)

Route parameters — making URLs dynamic

What if you want a route that works for any user ID — like /users/1 or /users/42? Use a colon (:) to mark a dynamic segment:

app.get('/users/:id', (req, res) => {
  // req.params.id holds whatever was in the URL
  const userId = req.params.id;
  res.send(`You requested user with ID: ${userId}`);
});

// Visiting /users/5 → "You requested user with ID: 5"
// Visiting /users/99 → "You requested user with ID: 99"

Understanding req and res

Every route handler receives two special objects. Think of them as the two sides of a conversation:

Object Full name What it contains Example use
req request What the client sent to you req.params.id, req.query.name
res response What you send back to the client res.send(), res.json()

Handling POST requests

A POST request is used to send data to the server — like submitting a form, creating a new account, or adding an item to a database. Unlike GET requests, POST requests carry a body of data.

Before your routes can read the body of a POST request, you need to add one line of setup — a middleware that tells Express to parse incoming JSON data automatically:

const express = require('express');
const app = express();

// ✅ This middleware lets us read JSON data sent in the request body
app.use(express.json());

// A POST route to create a new user
app.post('/users', (req, res) => {
  const { name, email } = req.body; // read the data sent by the client

  // In a real app you'd save to a database here
  console.log(`New user: \({name}, \){email}`);

  res.status(201).json({
    message: 'User created!',
    user: { name, email }
  });
});

app.listen(3000);

📦 What is middleware?

Middleware is code that runs between receiving a request and sending a response. express.json() is built-in middleware that reads the raw request body and automatically converts it into a JavaScript object available at req.body.

Testing your POST route

You can't test a POST route by just typing in a browser (that only sends GET requests). Use a tool like Postman or Requestlyto send a POST request with a JSON body like this:

{
  "name": "Alice",
  "email": "alice@example.com"
}

// Expected response:
{
  "message": "User created!",
  "user": {
    "name": "Alice",
    "email": "alice@example.com"
  }
}

Sending responses

Once Express matches a route, you need to send something back. The res object has several methods depending on what kind of response you want to send.

Method What it sends Common use case
res.send() Text or HTML string Simple messages, HTML pages
res.json() JSON data APIs returning objects or arrays
res.status() Sets the HTTP status code Always chain before .send() or .json()
res.sendFile() A file from the server Serving HTML files, images, PDFs
// 1. Send plain text
app.get('/hello', (req, res) => {
  res.send('Hello, World!');
});

// 2. Send JSON data (perfect for APIs)
app.get('/api/user', (req, res) => {
  res.json({
    name: 'Alice',
    age: 28,
    role: 'developer'
  });
});

// 3. Set a status code + send a message
app.get('/secret', (req, res) => {
  res.status(403).json({ error: 'Access denied' });
});

// 4. Catch-all 404 handler (always put this LAST)
app.use((req, res) => {
  res.status(404).send('Page not found!');
});

✅ Best practice

Always chain res.status() before .send() or .json() when you need to set a specific status code. The default status is 200 (success), but use 201 for created resources, 400 for bad requests, 404 for not found, and 500 for server errors.

Putting it all together

const express = require('express');
const app = express();
app.use(express.json()); // enable JSON parsing

// In-memory "database" (just a JS array for this demo)
let users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

// GET all users
app.get('/users', (req, res) => {
  res.json(users);
});

// GET one user by ID
app.get('/users/:id', (req, res) => {
  const id = Number(req.params.id)
  const user = users.find(u => u.id === id);
  if (!user) return res.status(404).json({ error: 'User not found' });
  res.json(user);
});

// POST create a new user
app.post('/users', (req, res) => {
  const newUser = {
    id: users.length + 1,
    name: req.body.name
  };
  users.push(newUser);
  res.status(201).json(newUser);
});

// 404 catch-all (must be LAST)
app.use((req, res) => {
  res.status(404).send('Route not found');
});

app.listen(3000, () =>
  console.log('🚀 Server running at http://localhost:3000')
);

Express Routing Structure at a Glance

Here's how a real Express app's routes might be laid out. Each URL pattern + HTTP method combination maps to exactly one handler function.

Express App — Route Map

Method Route Description
GET / Return the homepage or welcome message
GET /users Return a list of all users
GET /users/:id Return a single user by their ID
POST /users Create a new user from request body
PUT /users/:id Update an existing user by ID
DELETE /users/:id Delete a user by ID

Cheat sheet

Here's a summary of everything covered in this guide:

What you want to do The Express way
Create a server const app = express()
Handle a GET request app.get('/path', handler)
Handle a POST request app.post('/path', handler)
Read URL parameters req.params.id
Read POST body data req.body (after app.use(express.json()))
Send a text response res.send('text')
Send a JSON response res.json({ key: 'value' })
Set a status code res.status(201).json(...)
Start the server app.listen(3000)

HaPPy CoDiNg