First Express App (app.get, app.listen) · learncode.live

The Minimal Express Server

The simplest Express server requires just a few lines:

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

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

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

Run it with node index.js and visit http://localhost:3000 in your browser.

          Request                Response
Browser ────────→ Express ──────────────→ Browser
  │                 │                       │
  │  GET /          │   200 OK              │
  │  Host: local... │   "Hello World!"      │
  └─────────────────┘   Content-Type:       │
                        text/html           │
                          └──────────────────┘

Breaking Down app.listen

app.listen(port, callback) binds the server to a port:

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

It returns an http.Server instance. You can also store the reference:

const server = app.listen(3000);

server.on('listening', () => {
  console.log('Server is listening');
});

To gracefully shut down:

server.close(() => {
  console.log('Server closed');
});

Route Methods

Express supports all HTTP verbs as methods on app:

// GET - retrieve data
app.get('/users', (req, res) => {
  res.send('List of users');
});

// POST - create data
app.post('/users', (req, res) => {
  res.send('User created');
});

// PUT - update data (full replacement)
app.put('/users/:id', (req, res) => {
  res.send(`User ${req.params.id} updated`);
});

// PATCH - partial update
app.patch('/users/:id', (req, res) => {
  res.send(`User ${req.params.id} partially updated`);
});

// DELETE - remove data
app.delete('/users/:id', (req, res) => {
  res.send(`User ${req.params.id} deleted`);
});

Route Paths

Route paths can be strings, string patterns, or regular expressions:

Exact strings:

app.get('/about', handler);         // matches /about only
app.get('/contact', handler);       // matches /contact only

Route parameters (dynamic segments):

app.get('/users/:userId', handler);
// Matches /users/42, /users/john, etc.
// Access with req.params.userId

app.get('/users/:userId/posts/:postId', handler);
// Matches /users/42/posts/101
// req.params → { userId: '42', postId: '101' }

Query parameters:

app.get('/search', (req, res) => {
  // URL: /search?q=express&page=2
  const { q, page } = req.query;
  res.send(`Searching for "${q}" on page ${page}`);
});

The Request Object (req)

Express extends the Node.js req object with many useful properties:

PropertyDescriptionExample
req.paramsRoute parameters{ id: '42' }
req.queryQuery string{ name: 'john' }
req.bodyRequest body (requires middleware){ name: 'John' }
req.headersHTTP headers{ 'content-type': 'application/json' }
req.methodHTTP method'GET'
req.pathURL path'/users'
req.ipClient IP address'::1'
req.hostnameHostname'localhost'
app.get('/info', (req, res) => {
  console.log('Method:', req.method);
  console.log('Path:', req.path);
  console.log('Headers:', req.headers);
  console.log('IP:', req.ip);
  res.json({
    method: req.method,
    path: req.path,
    hostname: req.hostname,
    timestamp: Date.now()
  });
});

The Response Object (res)

Express provides powerful methods on the response object:

app.get('/response-demo', (req, res) => {
  // Send plain text
  res.send('Hello World');

  // Send JSON
  res.json({ message: 'Hello World' });

  // Send HTML
  res.send('<h1>Hello</h1>');

  // Send a file
  res.sendFile('/path/to/file.pdf');

  // Redirect
  res.redirect('/new-location');

  // Set status code
  res.status(404).send('Not Found');
});

Note: You can only call one send method per request - they end the response.

Common Status Codes

res.status(200).send('OK');              // 200 OK
res.status(201).json({ created: true }); // 201 Created
res.status(400).send('Bad Request');     // 400 Bad Request
res.status(401).send('Unauthorized');    // 401 Unauthorized
res.status(403).send('Forbidden');       // 403 Forbidden
res.status(404).send('Not Found');       // 404 Not Found
res.status(500).send('Server Error');    // 500 Internal Server Error

Chaining Methods

Express response methods support chaining:

res
  .status(201)
  .set('X-Custom-Header', 'value')
  .json({ success: true });

Full Example: Simple User API

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

// Sample data
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

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

// GET a single user by ID
app.get('/api/users/:id', (req, res) => {
  const id = parseInt(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);
});

// 404 handler for unknown routes
app.use((req, res) => {
  res.status(404).send('Route not found');
});

app.listen(port, () => {
  console.log(`API server at http://localhost:${port}`);
});

Key Takeaways

  • express() creates an application object
  • app.listen(port, callback) starts the server
  • Route methods (app.get, app.post, etc.) define endpoints
  • Route parameters (:param) capture dynamic URL segments
  • res.send(), res.json(), and res.status() control the response
  • Only one response method per request
Courses