Session Plan

Session outline

Exercises

  1. Server: Setup project

  2. DB schema: Setup MySQL database schema

  3. API: Snippets API exercises

    • Error handling and logging for the routes you create (choose appropriate status codes and response bodies).

Live coding

app.get vs app.use

Let's clarify the routing in Express using an Express router.

Code example can be found in the module materials and router.

Query parameters vs URL parameters

URL parameters

These are part of the URL path used to identify specific resources.

Example: GET /api/snippets/123 represented in our router by /api/snippets/:id

In the above URL, 123 is an ID of the snippet to fetch. The route indicates that we will only return this one resouce or nothing else. :id is dynamic, so that we can define one route and be sure to get and parse any ID passed. In the same time, passing an :id is required.

Query parameters

These come after the ? character and are usually key=value pairs, separated by &.

Example: GET /api/snippets?tag=popular

Used for sorting, filtering, pagination, or tracking, are usually optional. Can also be multiple values.

Code example can be found in the parameters file.

Route order

Code example can be found in the route order file

Middleware

Middleware is a generic term used for any software that acts as a connector between two other bits of software. In Express world, middleware is a layer that can be injected between a request and response and perform additional tasks.

You can find out more about Express middleware in the Express middleware documentation.

Code example of a sample middleware can be found in the middleware file

Error handling in Express

Error handling is how we make failures predictable and understandable for both users and developers.

At a high level:

  • Use HTTP status codes to communicate what happened (success, client error, server error).

  • Use logs to capture why something went wrong (stack traces, query details, internal IDs).

  • Keep responses to clients simple and safe, without leaking internal implementation details.

In Express, a typical pattern looks like this:

  • Validate incoming data at the start of a route. If it is invalid, respond with a 4xx status code and a short JSON error message.

  • Wrap asynchronous logic so that thrown errors or rejected promises are passed to next(err).

  • Use a custom error-handling middleware with the signature (err, req, res, next) at the bottom of your middleware stack:

    • Log err (and any useful context like req.method, req.path).

    • Respond once with a generic 500 error body like { "error": "Internal server error" }, or a more specific code if you know the problem.

You can find a small example of this pattern in the middleware file. Use this as a reference when running the error-handling live coding and exercise.

HTTP Status Codes Refresher

Here are some of the most commonly used:

2XX - Success

200 OK - The request succeeded, e.g. a webpage or API response loads as it should. 201 Created - A new resource was made, e.g. a new snippet or tag.

3XX - Redirection

301 Moved Permanently - The URL has changed, e.g. redirect from oldsite.com to newsite.com. 302 Found - A temporary redirect, e.g. redirecting Spanish visitors to the Spanish version of the website.

4XX - Client Errors

400 Bad Request - The request was invalid, e.g. form data missing or incorrect. 401 Unauthorized - You need to log in e.g. trying to access user features when logged out. 404 Not Found - Nothing at that URL e.g. a missing page or resource.

5XX - Server Errors

500 Internal Server Error - Generic server issue, e.g. something goes wrong in the backend. 503 Service Unavailable - Server is down or busy e.g. backend API is not running.

You can read more at the HTTP Status cheatsheet.

Client vs Server

Server-side errors should be designed for developers. Detailed errors help debugging and ultimately fixing issues easier. For example: if a database table is missing, record the missing table name and stack trace in your logs.

Client-side errors should be designed for users, including the correct HTTP status code. For example: in the missing database table case, simply return a 500 Internal Server Error and a useful message to the client to explain how to continue, without exposing internal details.

It's important to hide specific error details from the user for multiple reasons:

  1. Security – Revealing database names and other internal details can give attackers too many clues about your system which can make your app more vulnerable to exploitation.

  2. Privacy – Many internal errors can include sensitive data (e.g. user IDs, personal information) that shouldn't be exposed.

  3. User Experience – Some technical errors would confuse most users, so stick with simple, friendly messages that can help the user continue.

Last updated