Skip to content

Request & Response in Express.js

Understanding the request and response objects is essential for building Express applications. These objects provide access to incoming data and methods to send responses.

The Request Object (req)

The req object represents the HTTP request and contains properties for the request query string, parameters, body, headers, and more.

Request Properties

javascript
app.get('/example', (req, res) => {
  // URL and path
  console.log(req.url);          // /example?name=john
  console.log(req.path);         // /example
  console.log(req.originalUrl);  // /example?name=john
  console.log(req.baseUrl);      // Base URL if using router

  // HTTP method
  console.log(req.method);       // GET

  // Protocol and host
  console.log(req.protocol);     // http or https
  console.log(req.hostname);     // localhost
  console.log(req.ip);           // Client IP address

  // Check if secure (HTTPS)
  console.log(req.secure);       // true or false

  // Check if XHR (Ajax) request
  console.log(req.xhr);          // true or false
});

Route Parameters

javascript
// GET /users/123/posts/456
app.get('/users/:userId/posts/:postId', (req, res) => {
  console.log(req.params);
  // { userId: '123', postId: '456' }

  const { userId, postId } = req.params;
  res.json({ userId, postId });
});

Query String

javascript
// GET /search?q=express&page=2&limit=10
app.get('/search', (req, res) => {
  console.log(req.query);
  // { q: 'express', page: '2', limit: '10' }

  const { q, page = 1, limit = 20 } = req.query;
  res.json({
    query: q,
    page: parseInt(page),
    limit: parseInt(limit)
  });
});

// GET /filter?tags=js&tags=node&tags=express
app.get('/filter', (req, res) => {
  console.log(req.query.tags);
  // ['js', 'node', 'express']
});

Request Body

javascript
// Enable body parsing
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// POST with JSON body
app.post('/api/users', (req, res) => {
  console.log(req.body);
  // { name: 'John', email: 'john@example.com' }

  const { name, email } = req.body;
  res.json({ name, email });
});

Request Headers

javascript
app.get('/headers', (req, res) => {
  // Get all headers
  console.log(req.headers);

  // Get specific header (case-insensitive)
  console.log(req.get('Content-Type'));
  console.log(req.get('Authorization'));
  console.log(req.headers['user-agent']);

  // Check Accept header
  console.log(req.accepts('html'));        // 'html' or false
  console.log(req.accepts('json'));        // 'json' or false
  console.log(req.accepts(['html', 'json']));

  res.json({ headers: req.headers });
});

Cookies

javascript
const cookieParser = require('cookie-parser');
app.use(cookieParser('secret-key'));

app.get('/cookies', (req, res) => {
  // Unsigned cookies
  console.log(req.cookies);
  // { theme: 'dark', lang: 'en' }

  // Signed cookies
  console.log(req.signedCookies);
  // { sessionId: 'abc123' }

  res.json({
    cookies: req.cookies,
    signedCookies: req.signedCookies
  });
});

The Response Object (res)

The res object represents the HTTP response that Express sends when it receives a request.

Sending Responses

javascript
// Send string
app.get('/text', (req, res) => {
  res.send('Hello World');
});

// Send HTML
app.get('/html', (req, res) => {
  res.send('<h1>Hello World</h1>');
});

// Send JSON
app.get('/json', (req, res) => {
  res.json({
    message: 'Hello World',
    timestamp: new Date()
  });
});

// Send JSON with pretty printing
app.get('/pretty', (req, res) => {
  res.set('Content-Type', 'application/json');
  res.send(JSON.stringify({ message: 'Hello' }, null, 2));
});

Status Codes

javascript
// Set status and send
app.get('/created', (req, res) => {
  res.status(201).json({ message: 'Created' });
});

// Send status only
app.get('/no-content', (req, res) => {
  res.sendStatus(204); // No Content
});

// Common status codes
app.post('/users', (req, res) => {
  // 200 OK - Success
  // 201 Created - Resource created
  // 204 No Content - Success with no body
  // 400 Bad Request - Invalid data
  // 401 Unauthorized - Not authenticated
  // 403 Forbidden - Not authorized
  // 404 Not Found - Resource not found
  // 500 Internal Server Error

  res.status(201).json({ id: 1, ...req.body });
});

Response Headers

javascript
app.get('/headers', (req, res) => {
  // Set single header
  res.set('X-Custom-Header', 'value');
  res.set('Content-Type', 'application/json');

  // Set multiple headers
  res.set({
    'X-Request-Id': '12345',
    'X-Response-Time': '100ms'
  });

  // Append to existing header
  res.append('Set-Cookie', 'foo=bar');
  res.append('Set-Cookie', 'baz=qux');

  // Remove header
  res.removeHeader('X-Powered-By');

  res.json({ message: 'Headers set' });
});

Cookies

javascript
app.get('/set-cookie', (req, res) => {
  // Simple cookie
  res.cookie('name', 'value');

  // Cookie with options
  res.cookie('session', 'abc123', {
    httpOnly: true,     // Not accessible via JavaScript
    secure: true,       // HTTPS only
    sameSite: 'strict', // CSRF protection
    maxAge: 24 * 60 * 60 * 1000, // 1 day in ms
    path: '/',          // Cookie path
    domain: '.example.com' // Cookie domain
  });

  // Signed cookie
  res.cookie('userId', '123', { signed: true });

  res.send('Cookies set');
});

app.get('/clear-cookie', (req, res) => {
  res.clearCookie('name');
  res.clearCookie('session', { path: '/' });
  res.send('Cookies cleared');
});

Redirects

javascript
// Simple redirect (302 by default)
app.get('/old-page', (req, res) => {
  res.redirect('/new-page');
});

// Redirect with status
app.get('/moved', (req, res) => {
  res.redirect(301, '/permanent-location');
});

// Redirect to external URL
app.get('/google', (req, res) => {
  res.redirect('https://google.com');
});

// Redirect back (uses Referer header)
app.post('/action', (req, res) => {
  // Process action...
  res.redirect('back');
});

// Redirect with query string
app.get('/search', (req, res) => {
  res.redirect('/results?q=' + encodeURIComponent(req.query.q));
});

Sending Files

javascript
const path = require('path');

// Send file
app.get('/file', (req, res) => {
  res.sendFile(path.join(__dirname, 'files', 'document.pdf'));
});

// Send file with options
app.get('/image', (req, res) => {
  res.sendFile('image.png', {
    root: path.join(__dirname, 'public'),
    headers: {
      'Cache-Control': 'max-age=31536000'
    }
  }, (err) => {
    if (err) {
      res.status(404).send('File not found');
    }
  });
});

// Download file (prompts save dialog)
app.get('/download', (req, res) => {
  res.download(
    path.join(__dirname, 'files', 'report.pdf'),
    'monthly-report.pdf', // Custom filename
    (err) => {
      if (err) {
        res.status(500).send('Download failed');
      }
    }
  );
});

Content Negotiation

javascript
app.get('/data', (req, res) => {
  const data = { name: 'John', age: 30 };

  res.format({
    'text/plain': () => {
      res.send(`Name: ${data.name}, Age: ${data.age}`);
    },
    'text/html': () => {
      res.send(`<p>Name: ${data.name}</p><p>Age: ${data.age}</p>`);
    },
    'application/json': () => {
      res.json(data);
    },
    default: () => {
      res.status(406).send('Not Acceptable');
    }
  });
});

Streaming Responses

javascript
const fs = require('fs');

app.get('/stream', (req, res) => {
  const stream = fs.createReadStream('large-file.txt');

  res.set('Content-Type', 'text/plain');
  stream.pipe(res);
});

// Server-Sent Events
app.get('/events', (req, res) => {
  res.set({
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  const interval = setInterval(() => {
    res.write(`data: ${JSON.stringify({ time: new Date() })}\n\n`);
  }, 1000);

  req.on('close', () => {
    clearInterval(interval);
  });
});

Request Lifecycle

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

app.use(express.json());

// Track request timing
app.use((req, res, next) => {
  req.startTime = Date.now();

  // Override res.json to add timing
  const originalJson = res.json.bind(res);
  res.json = (data) => {
    const duration = Date.now() - req.startTime;
    res.set('X-Response-Time', `${duration}ms`);
    return originalJson(data);
  };

  next();
});

app.get('/api/data', (req, res) => {
  // Simulate processing
  setTimeout(() => {
    res.json({ message: 'Done' });
  }, 100);
});

app.listen(3000);

Practical Example

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

app.use(express.json());

// Products API
const products = [
  { id: 1, name: 'Laptop', price: 999 },
  { id: 2, name: 'Phone', price: 699 }
];

app.get('/api/products', (req, res) => {
  const { minPrice, maxPrice, sort } = req.query;

  let result = [...products];

  // Filter by price
  if (minPrice) {
    result = result.filter(p => p.price >= parseInt(minPrice));
  }
  if (maxPrice) {
    result = result.filter(p => p.price <= parseInt(maxPrice));
  }

  // Sort
  if (sort === 'price') {
    result.sort((a, b) => a.price - b.price);
  } else if (sort === '-price') {
    result.sort((a, b) => b.price - a.price);
  }

  res.json({
    count: result.length,
    data: result
  });
});

app.get('/api/products/:id', (req, res) => {
  const product = products.find(p => p.id === parseInt(req.params.id));

  if (!product) {
    return res.status(404).json({ error: 'Product not found' });
  }

  // Content negotiation
  res.format({
    json: () => res.json(product),
    html: () => res.send(`<h1>${product.name}</h1><p>$${product.price}</p>`),
    default: () => res.json(product)
  });
});

app.listen(3000);

Summary

In this tutorial, you learned:

  • Request object properties and methods
  • Accessing params, query, body, and headers
  • Response methods (send, json, status)
  • Setting headers and cookies
  • Redirects and file downloads
  • Content negotiation
  • Streaming responses

Next, we'll explore Template Engines for rendering dynamic HTML.