Express

Fast, unopinionated, minimalist web framework for Node.js

Álvaro José Agámez Licha

Senior Software Engineer

https://github.com/aagamezl

https://x.com/aagamezl

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. It's essentially a layer built on top of Node.js that makes server-side development much easier.

 

  • Handle routing (URL handling).
  • Middleware chaining.
  • Build REST APIs quickly.
  • Easy integration with template engines.

What is Express?

Start a new Node.js project and install Express with the following commands:

What is Express?

npm init -y
npm pkg set type="module"
npm i express

Routing in Express defines how the server responds to client requests on a specific path and method (GET, POST, etc.).

 

We can define as many routes as our API needs, and although we have complete freedom in how we name our routes, there are some best practices that are important to keep in mind.

Routing in Express

Routing refers to how an application responds to a client request to a particular endpoint (URI) with a specific HTTP request method (GET, POST, etc.).
 

app.METHOD(PATH, HANDLER)

  • app is an instance of express
  • METHOD is an HTTP request method (GET, POST, etc.)
  • PATH is a path on the server
  • HANDLER is the function executed when the route is matched

Basic Routing Structure

  1. Use Nouns (Not Verbs) for Resources
  2. Use Plural Nouns for Collections
  3. Keep URLs Lowercase
  4. Use Hyphens for Multi-word Paths
  5. Nest Resources Properly
  6. Use Forward Slashes for Hierarchy
  7. Use Query Parameters for Filtering and Sorting
  8. Be Consistent

Routing Good Practices

Example Of Well-Structured Routes

// User routes
router.get('/users', userController.getAll);
router.post('/users', userController.create);
router.get('/users/:userId', userController.getById);
router.put('/users/:userId', userController.update);
router.delete('/users/:userId', userController.delete);

// Nested routes
router.get('/users/:userId/orders', orderController.getUserOrders);
router.post('/users/:userId/orders', orderController.createUserOrder);

// Special actions
router.post('/users/:userId/activate', userController.activate);
router.post('/users/:userId/deactivate', userController.deactivate);

// Filtering examples
router.get('/products', productController.getAll);
router.get('/products?category=:category', productController.getByCategory);

app.use() is used to mount middleware functions. These functions have access to the request object (req), the response object (res), and the next middleware function in the application's request-response cycle.

app.use()

app.use((req, res, next) => {
  console.log('Time:', Date.now());
  
  next(); // Pass control to the next middleware
});

Handles GET requests to a specific path for fetching resources.

app.get()

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

Route parameters are named URL segments used to capture values at specific positions in the URL.

Route Parameters

app.get('/users/:userId', (req, res) => {
  res.send(`User ID: ${req.params.userId}`);
});

Example request: GET /users/42
Response: User ID: 42

Query parameters are key-value pairs that appear after the ? in a URL.

Query Parameters

app.get('/users', (req, res) => {
  const limit = req.query.limit ?? 10;
  res.send(`Showing ${limit} users`);
});

Example request: GET /users?limit=5
Response: Showing 5 users

Express matches routes in the order they are defined. The first matching route will handle the request.

 

Important rules:

  • Specific routes should come before generic ones
  • Error handlers and 404 routes should come last

Route Order Matters!

Route Order Matters!

// This will match /users/new AND /users/:id if placed first
app.get('/users/:id', (req, res) => {
  res.send(`User ID: ${req.params.id}`);
});

// This needs to come first to be matched properly
app.get('/users/new', (req, res) => {
  res.send('New user form');
});

// Correct order:
app.get('/users/new', (req, res) => {
  res.send('New user form');
});

app.get('/users/:id', (req, res) => {
  res.send(`User ID: ${req.params.id}`);
});

Logging And Debugging

Understanding the flow of execution is crucial. Let's add logging:

app.use((req, res, next) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
  next();
});

app.get('/debug', (req, res, next) => {
  console.log('Middleware before response');
  next();
}, (req, res) => {
  console.log('Sending response');
  res.send('Debug route');
  console.log('Response sent');
});

Logging And Debugging

  • Use console.log to track execution flow
  • Check the order of middleware registration
  • Remember that res.send() ends the response
  • Use tools like Postman to test routes
  • Response is sent to client
  • Use Node.js debugger (with VS Code)

Summary Of Execution Order

  • Request comes in
  • Matches middleware in registration order (app.use)
  • Matches route handlers in registration order
  • Executes all matching middleware/handlers until response is sent
  • If no response is sent, falls through to 404 handler
  • Response is sent to client

Coding Time

HyF Node.js Week 02

By Alvaro Agamez

HyF Node.js Week 02

  • 65